種類並查集
1.定義:rank為0代表父節點與子節點是同一物種,rank為1代表父節點吃子節點,rank為2代表子節點吃父節點。
這個定義與輸入的type相符合,type-1==1表示x吃y,type-1==0表示同一物種
2.路徑壓縮:兒子對爺爺的關係==(兒子對父親的關係+父親對爺爺的關係)%3。可通過窮舉法證明。
3.集合合併:以左為尊處理f【】陣列,rank陣列的值根據兩次使用路徑壓縮推導公式得來
#include #include #define n 50005
using namespace std;
int f[n], rank[n];
//rank為0代表父節點與子節點是同一物種,rank為1代表父節點吃子節點,rank為2代表子節點吃父節點
int n, k;
void init()
}int find(int x)
}int main()
x = find(a); y = find(b);
if (x != y)//確定新關係
else//已知在同一集合,即關係已經確定,判斷是否正確
}} printf("%d\n", ans);
return 0;
}
第二種寫法:
由於n和k很大,故需高效的維護動物之間的關係,對於每只動物i建立3個元素i-a,i-b,i-c,
並用這3*n個元素建立並查集,這個並查集維護如下資訊:
1.i-x表示「i屬於種類x」
2.並查集裡到達每乙個組表示組內所有元素代表的情況都同時發生或者不發生
例如,如果i-a和j-b在同乙個組裡,就表示如果i屬於種類a那麼j一定屬於種類b,反之亦然。
因此,對於每一條資訊,只需按照如下操作即可:
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
注意:在合併之前,需要先判斷合併是否會產生矛盾
由於從始至終只知道相對關係,同時維護了三種可能,所以判斷矛盾的時候任選一種判斷就可以了。
#include #define n 50005
int f[3 * n];
int n, k;
void init()
int find(int x)
void merge(int x, int y)
int same(int x, int y)
int main()
if (type == 1)
}else
}} printf("%d\n", ans);
return 0;
}
POJ 1182 食物鏈 (種類並查集)
食物鏈time limit 1000ms memory limit 10000k total submissions 47729 accepted 13895 description 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n編...
poj 1182食物鏈 種類並查集
食物鏈 time limit 1000ms memory limit 10000k total submissions 49310 accepted 14382 description 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n...
POJ 1182 食物鏈(種類並查集)
食物鏈time limit 1000ms memory limit 10000k total submissions 63592 accepted 18670 description 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n編...