POJ 1182 食物鏈 並查集

2021-09-22 20:23:13 字數 1748 閱讀 1993

此題按照《挑戰程式設計競賽(第2版)》p89的解法,不容易想到,但想清楚了**還是比較直觀的。

並查集模板(包含了記錄高度的rank陣列和查詢時狀態壓縮)

1

const

int max_n=50002*3;2

intpar[max_n];

3int

rank[max_n];4//

初始化,根為自身,高度為0

5void init(int

scab)612

}13//查詢,途徑的所有結點都直接連到根上

14int find(int

x)15

19//

合併,把短鏈連線到長鏈上,保持結點高度的相對關係

20int unite(int x,int

y)21

26 par[y]=x;

27if(rank[x]==rank[y]) rank[x]++;

28return1;

29 }

並查集實現

並查集是用於維護「屬於同一集合」的資料結構,然而這道題的「屬於同一集合」並不指「是同類」,而是指「這幾個情況若發生必然同時發生」。

我們從理解題意開始:

有n只動物,分別編號為1,2,...,n。所有動物屬於a,b,c類中的一種,類之間有天然的a**,b吃c,c吃a的關係。

按如下兩種格式順序給出共k條資訊(只表達了相對關係):

1 x y: x,y是同類

2 x y: x吃y

每條資訊若不符合常理(編號大於n,或自己吃自己)或與已有資訊矛盾,則為錯誤。

問這k條資訊有幾條錯誤?

由於a,b,c之間的吃與被吃關係構成乙個迴圈,所以三類的等級關係根本上也是相對的,那麼每條資訊都可以翻譯成三種可能的實際情況。同時維護這三種可能

,就需要為每個動物x分配三個陣列元素,分別表示x是a,x是b,x是c這三個事件。

同屬乙個集合的事件意味著「若發生必然同時發生」。

並查集需要用乙個陣列儲存每個元素「屬於哪一集合」,那麼可以開乙個長度為n*3的陣列,用x,x+n,x+n*2分別表示x是a,x是b,x是c。

表示x與y是同類,需要維護這三種可能

unite(x,y);        //x,y都是a

unite(x+n,y+n);     //x,y都是b

unite(x+2*n,y+2*n); //x,y都是c

表示x吃y,需要維護這三種可能

unite(x,y+n);    //x是a,y是b

unite(x+n,y+2*n);  //x是b,y是c

unite(x+2*n,y);  //x是c,y是a

想清楚了道理,**就比較好理解了。注意由於從始至終只知道相對關係,同時維護了三種可能,所以判斷矛盾的時候任選一種判斷就可以了。

1

intmain()215

if(d==1

)16 25}

26else

if(d==2)27

38}39}

40 printf("

%d\n

",ans);

41return0;

42 }

oj執行結果如下:

這道題使我對並查集有了新的認識,想清楚「同屬乙個集合」代表什麼很重要,不一定就是題目限定的「屬於同一種」。

分析問題的難度有時會大於程式設計的難度,如果說**能力可以通過刷題習得,那麼分析問題的能力真的需要足夠的知識儲備和一些「創造性思維」了。

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 食物鏈 (並查集)

食物鏈time limit 1000ms memory limit 10000k total submissions 48713 accepted 14202 description 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n編...

POJ 1182 食物鏈(並查集)

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