第一次作種類並查集的問題ios
想了一會,發現其本質以下:spa
知得題目中的任意兩個變量之間的關係,而後根據關係創建並查集,並在尋找祖先的時候根據關係層層修改code
有的時候種類並查集能夠大大減小代碼量blog
動物王國中有三類動物 A,B,C,這三類動物的食物鏈構成了有趣的環形。A 吃 B,Bio
吃 C,C 吃 A。模板
現有 N 個動物,以 1 - N 編號。每一個動物都是 A,B,C 中的一種,可是咱們並不知道class
stream
有人用兩種說法對這 N 個動物所構成的食物鏈關係進行描述:變量
第一種說法是「1 X Y」,表示 X 和 Y 是同類。nio
第二種說法是「2 X Y」,表示 X 吃 Y 。
此人對 N 個動物,用上述兩種說法,一句接一句地說出 K 句話,這 K 句話有的是真
的,有的是假的。當一句話知足下列三條之一時,這句話就是假話,不然就是真話。
• 當前的話與前面的某些真的話衝突,就是假話
• 當前的話中 X 或 Y 比 N 大,就是假話
• 當前的話表示 X 吃 X,就是假話
你的任務是根據給定的 N 和 K 句話,輸出假話的總數。
輸入格式:
第一行兩個整數,N,K,表示有 N 個動物,K 句話。
第二行開始每行一句話(按照題目要求,見樣例)
輸出格式:
//種類並查集 #include<iostream> #include<cstdio> using namespace std; int fa[300866]; //同類關係1-n //a獵殺b a:1-n b:n-2n //a被b獵殺 a:1-n b:2n-3n int n,m,ans; int relation,u,v; int find(int u) { return fa[u] == u ? u : fa[u] = find(fa[u]); } void unionn(int u,int v) //將在u與v上的關係合併,就是說u和v是同類 { int fa_u = find(u); int fa_v = find(v); fa[fa_u] = fa_v; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n * 3;i++) fa[i] = i; while(m--) { scanf("%d%d%d",&relation,&u,&v); if(u > n || v > n) { ans++; continue; } if(relation == 1) //u和v是同類 { if(find(u + n) == find(v) || find(u + n + n) == find(v)) //能夠推知不知足 { ans++; continue; } else { unionn(u,v); unionn(u + n,v + n); unionn(u + n + n,v + n + n); } } if(relation == 2) //u捕食v { if(u == v || find(u) == find(v) || find(u + n + n) == find(v)) //能夠推知不知足 { ans++; continue; } else { unionn(u,v + n + n); //u與v的天敵是同類 unionn(u + n,v); unionn(u + n + n,v + n); } } } printf("%d",ans); return 0; }