POJ 1182 食物鏈 (並查集)

2021-06-29 04:30:07 字數 3453 閱讀 9692

食物鏈time limit:1000ms

memory limit:10000k

total submissions:48713

accepted:14202

description

動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b, b吃c,c吃a。 

現有n個動物,以1-n編號。每個動物都是a,b,c中的一種,但是我們並不知道它到底是哪一種。 

有人用兩種說法對這n個動物所構成的食物鏈關係進行描述: 

第一種說法是"1 x y",表示x和y是同類。 

第二種說法是"2 x y",表示x吃y。 

此人對n個動物,用上述兩種說法,一句接一句地說出k句話,這k句話有的是真的,有的是假的。當一句話滿足下列三條之一時,這句話就是假話,否則就是真話。 

1) 當前的話與前面的某些真的話衝突,就是假話; 

2) 當前的話中x或y比n大,就是假話; 

3) 當前的話表示x吃x,就是假話。 

你的任務是根據給定的n(1 <= n <= 50,000)和k句話(0 <= k <= 100,000),輸出假話的總數。 

input

第一行是兩個整數n和k,以乙個空格分隔。 

以下k行每行是三個正整數 d,x,y,兩數之間用乙個空格隔開,其中d表示說法的種類。 

若d=1,則表示x和y是同類。 

若d=2,則表示x吃y。

output

只有乙個整數,表示假話的數目。

sample input

100 7

1 101 1

2 1 2

2 2 3

2 3 3

1 1 3

2 3 1

1 5 5

sample output

3

經典的並查集  下面摘抄挑戰的解法

今天在《挑戰程式設計競賽》中看到對於這題一種獨特的寫法,巧妙應用了並查集,於是理解後摘抄下來分享一下。

由於n和k很大,所以必須高效地維護動物之間的關係,並快速判斷是否產生了矛盾。並查集是維護 「屬於同一組」 的資料結構,但是在本題中,並不只有屬於同一類的資訊,還有捕食關係的存在。因此需要開動腦筋維護這些關係。

對於每只動物i建立3個元素i-a, i-b, i-c, 並用這3*n個元素建立並查集。這個並查集維護如下資訊:

① i-x 表示 「i屬於種類x」。

②並查集裡的每乙個組表示組內所有元素代表的情況都同時發生或不發生。

例如,如果i-a和j-b在同乙個組裡,就表示如果i屬於種類a那麼j一定屬於種類b,如果j屬於種類b那麼i一定屬於種類a。因此,對於每一條資訊,只需要按照下面進行操作就可以了。

1)第一種,x和y屬於同一種類———合併x-a和y-a、x-b和y-b、x-c和y-c。

2)第二種,x吃y—————————合併x-a和y-b、x-b和y-c、x-c和y-a。

不過在合併之前需要先判斷合併是否會產生矛盾。例如在第一種資訊的情況下,需要檢查比如x-a和y-b或者y-c是否在同一組等資訊。

ac**如下:

//

// poj 1182 食物鏈

//// created by taosama on 2015-03-16

//#include #include #include #include #include #include #include #include #include #include #include #include #include #define clr(x,y) memset(x, y, sizeof(x))

using namespace std;

const int inf = 0x3f3f3f3f;

const int mod = 1e9 + 7;

const int n = 50000;

int n, k, par[3 * n + 5], rank[3 * n + 5];

void init(int n)

}int find(int x)

void unite(int x, int y) else

}bool same(int x, int y)

int main()

if(op == 1)

} else

} }cout << ans << endl;

return 0;

}

網上的另一種解法:

1.p[x]表示x根結點。r[x]表示p[x]與x關係。r[x]=0 表示p[x]與x同類;1表示p[x]吃x;2表示x吃p[x]。

2.怎樣劃分乙個集合呢?

注意,這裡不是根據x與p[x]是否是同類來劃分。而是根據「x與p[x]能否確定兩者之間關係」來劃分,若能確定x與p[x]關係,則它們同屬乙個集合

3.怎樣判斷一句話是不是假話?

假設已讀入d ,x ,y ,先利用findset()函式得到x,y所在集合代表元素fx,fy,若它們在同一集合(即fx==fy)則可以判斷這句話真偽:

若 d==1 而 r[x]!=r[y] 則此話為假.(d==1 表示x與y為同類,而從r[x]!=r[y]可以推出 x 與 y 不同類.矛盾.)

若 d==2 而 r[x]==r[y](x與y為同類)或者r[x]==(r[y]+1)%3(y吃x)則此話為假。

4.上個問題中r[x]==(r[y]+1)%3這個式子怎樣推來?

假設有y吃x,那麼r[x]和r[y]值是怎樣?

我們來列舉一下: 

r[x]=0&&r[y]=2 

r[x]=1&&r[y]=0

r[x]=2&&r[y]=1

稍微觀察一下就知道r[x]=(r[y]+1)%3;

事實上,對於上個問題有更一般判斷方法:

若(r[y]-r[x]+3)%3!=d-1 ,則此話為假.

5.其他注意事項:

在union(d,x,y)過程中若將s(fy)合併到s(fx)上,則相應r[fy]必須更新為fy相對於fx關係。怎樣得到更新關係式?

r[fy]=(r[x]-r[y]+d+3)%3;

ac**如下:

#includeconst int n=50001;

int p[n],r[n],n;

int findset(int x)

return p[x];

}bool union(int d,int x,int y)

p[fy]=fx;

r[fy]=(r[x]-r[y]+d+3)%3;

return 0;

}int main()

if(union(d-1,x,y))ans++;

} printf("%d\n",ans);

return 0;

}

POJ 1182 食物鏈 並查集

此題利用並查集解決。對於每只動物i建立3個元素i a,i b,i c,並用這3 n個元素建立並查集。1 i x表示 i屬於種類x 2 並查集你的每一組表示組內所有元素代表的情況同時發生或不發生。對於每一條資訊,只需要按照下列操作即可 1.第一種 x,y同類,合併x a和y a x b和y b x c...

POJ 1182 食物鏈(並查集)

description 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n編號。每個動物都是a,b,c中的一種,但是我們並不知道它到底是哪一種。有人用兩種說法對這n個動物所構成的食物鏈關係進行描述 第一種說法是 1 x y 表示x和y是...

poj1182食物鏈 (並查集)

題目在這裡喲 和之前判斷蟲子是否有同性戀一樣 不是因為腦洞太大 都是分層的 取模的啊啊啊啊啊仔細觀察一下兩個 相似度好高好高哦哦 include include includeusing namespace std int total int n,m,a,b,c int f 500005 rank ...