题意:现在有三个物种,形成一种循环```好吧不装逼我们石头剪刀布```就是有 n 个动物,每个动物已经确定自己会出石头剪刀或者布,但我们并不知道,然后每次拿两只比较,告诉你平局或者谁胜,问这些里面有多少是假的。如果没有出现过逻辑错误都算作正确的,如果某一个与之前已经得到的结论矛盾或自身有错则算是假的。

定0、1、2,1>0,2>1,0>2,然后就可以计算两个动物的差值了,所以就能用带权并查集建立关系,然后每个元素的权值就是与祖先节点的值的差值,根据mod3可以累加转换。然后用并查集合并判断就可以了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 
 6 int fa[50005],num[50005],n,m;
 7 
 8 void init(){
 9     for(int i=1;i<=n;i++){
10         fa[i]=i;
11         num[i]=0;
12     }
13 }
14 
15 int find(int x){
16     int r=x,t1,t2,c=0;
17     while(r!=fa[r]){
18         c+=num[r];
19         r=fa[r];
20     }
21     while(x!=r){
22         t1=fa[x];
23         t2=c-num[x];
24         num[x]=c%3;
25         fa[x]=r;
26         x=t1;
27         c=t2;
28     }
29     return r;
30 }
31 
32 int main(){
33     scanf("%d%d",&n,&m);
34         int a,b,v,i,ans=0;
35         init();
36         for(i=1;i<=m;i++){
37             scanf("%d%d%d",&v,&a,&b);
38             if(a>n||b>n||(a==b&&v==2))ans++;
39             else if(a==b&&v==1)continue;
40             else{
41                 int x=find(a),y=find(b);
42                 if(x==y){
43                     if((((num[a]-num[b])%3)+3)%3!=(v-1))ans++;
44                 }
45                 else{
46                     fa[x]=y;
47                     num[x]=((num[b]+(v-1)-num[a])%3+3)%3;
48                 }
49             }
50         }
51         printf("%d\n",ans);
52     
53     return 0;
54 }
View Code