带权并查集

 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 }

 

 

posted @ 2021-10-28 18:37  Hell0er  阅读(25)  评论(0编辑  收藏  举报