题目描述
动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形。A 吃 B,B
吃 C,C 吃 A。
现有 N 个动物,以 1 - N 编号。每个动物都是 A,B,C 中的一种,但是我们并不知道
它到底是哪一种。
有人用两种说法对这 N 个动物所构成的食物链关系进行描述:
第一种说法是“1 X Y”,表示 X 和 Y 是同类。
第二种说法是“2 X Y”,表示 X 吃 Y 。
此人对 N 个动物,用上述两种说法,一句接一句地说出 K 句话,这 K 句话有的是真
的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
• 当前的话与前面的某些真的话冲突,就是假话
• 当前的话中 X 或 Y 比 N 大,就是假话
• 当前的话表示 X 吃 X,就是假话
你的任务是根据给定的 N 和 K 句话,输出假话的总数。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int fa[maxn],rnk[maxn];//rnk点与根的关系
int n,k;
void init(int x){
for(int a=0;a<=x;a++){
fa[a]=a;
rnk[a]=0;
}
}
int findfa(int x){
if(fa[x]==x)
return x;
else{
int mid=fa[x];
fa[x]=findfa(fa[x]);//压缩
rnk[x]=(rnk[x]+rnk[mid])%3;//节点与根的关系 rnk[mid]是mid与根结点的关系
return fa[x];//第二个rnk[x]是当前的点到压缩前的根的关系,rnk【mid】是之前的根到当前的根的关系,两者相加即为当前的点到当前的根的关系
}
}
void merge(int r,int x,int y){
int fx=findfa(x);
int fy=findfa(y);
if(fx!=fy){
fa[fx]=fy;
rnk[fx]=(rnk[y]-rnk[x]+r+3)%3;
}
}
bool check(int a,int b,int c){
if (b>n||c>n||b<1||c<1) {
return false;
}
if(a==1&&b==c)
return false;
int fb=findfa(b);
int fc=findfa(c);
if(fb==fc)
return a==(rnk[b]-rnk[c]%3+3)%3;
else
return true;
}
int main()
{
int ans = 0;
scanf("%d %d",&n,&k);
init(n);
for (int a=0; a<k; a++) {
int o,p,q;
cin>>o>>p>>q;
o--;
if(check(o,p,q))
merge(o,p,q);
else
ans++;
}
printf("%d\n",ans);
return 0;
}