题意:现在有三个物种,形成一种循环```好吧不装逼我们石头剪刀布```就是有 n 个动物,每个动物已经确定自己会出石头剪刀或者布,但我们并不知道,然后每次拿两只比较,告诉你平局或者谁胜,问这些里面有多少是假的。如果没有出现过逻辑错误都算作正确的,如果某一个与之前已经得到的结论矛盾或自身有错则算是假的。
定0、1、2,1>0,2>1,0>2,然后就可以计算两个动物的差值了,所以就能用带权并查集建立关系,然后每个元素的权值就是与祖先节点的值的差值,根据mod3可以累加转换。然后用并查集合并判断就可以了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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
",ans);
52
53 return 0;
54 }