带权并查集
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 const int MAXN=50010; 6 int n,k; 7 int head[MAXN]; 8 int re[MAXN]; 9 10 int root(int x) 11 { 12 int rt=head[x]; 13 if (x!=rt) 14 { 15 head[x]=root(rt); 16 re[x]=(re[x]+re[rt])%3; 17 return head[x]; 18 } 19 else return rt; 20 } 21 22 int main() 23 { 24 scanf("%d%d",&n,&k); 25 for (int i=1;i<=n;i++) //init 26 { 27 head[i]=i; 28 re[i]=0; //将根初始化为同类 29 } 30 31 int ans=0; 32 for (int i=1;i<=k;i++) 33 { 34 int opt,x,y; 35 scanf("%d%d%d",&opt,&x,&y); 36 if (x>n || y>n) 37 { 38 ans++; 39 continue; 40 } 41 if (opt==1) //x与y同类 42 { 43 int a=root(x),b=root(y); 44 if (a==b) 45 { 46 if (re[x]!=re[y]) ans++; 47 } 48 else 49 { 50 head[a]=b; 51 re[a]=(3-re[x]+re[y])%3; 52 } 53 } 54 else //x吃y 55 { 56 if (x==y) 57 { 58 ans++; 59 continue; 60 } 61 int a=root(x),b=root(y); 62 if (a==b) 63 { 64 int r=(re[x]-re[y]+3)%3; 65 if (r!=1) ans++; 66 } 67 else 68 { 69 head[a]=b; 70 re[a]=(3-re[x]+re[y]+1)%3; 71 } 72 } 73 } 74 printf("%d\n",ans); 75 76 return 0; 77 }