并查集进阶,除了用父亲数组保存父结点外,再用一个数组表示子结点与父结点之间的关系,查找与合并时都涉及到关系数组的修改。

 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 }