并查集进阶,除了用父亲数组保存父结点外,再用一个数组表示子结点与父结点之间的关系,查找与合并时都涉及到关系数组的修改。
1 #include <stdio.h> 2 #include <string.h> 3 int rank[50010],fa[50010]; 4 int find(int n) 5 { 6 int t = fa[n]; 7 if(fa[n] != n) 8 fa[n] = find(fa[n]); 9 rank[n] = (rank[n]+rank[t])%3; 10 return fa[n]; 11 } 12 void uni(int x,int y,int h) 13 { 14 int a = find(x); 15 int b = find(y); 16 fa[a] = b; 17 rank[a] = (rank[y]-rank[x]+3+h)%3; 18 } 19 int main() 20 { 21 int n,k,i,f,a,b,cnt=0; 22 scanf("%d%d",&n,&k); 23 for(i = 0; i < n; i++) 24 fa[i] = i; 25 while(k--) 26 { 27 scanf("%d%d%d",&f,&a,&b); 28 if(a>n || b>n) 29 {cnt++; continue;} 30 if(f==1) 31 { 32 if(find(a)==find(b)) 33 { 34 if(rank[a]!=rank[b]) 35 cnt++; 36 } 37 else uni(a,b,0); 38 } 39 else 40 { 41 if(find(a)==find(b)) 42 { 43 if(rank[a]!=(rank[b]+1)%3) 44 cnt++; 45 } 46 else uni(a,b,1); 47 } 48 } 49 printf("%d",cnt); 50 return 0; 51 }