这个题的做法2比做法1好想
以下距离都在 mod 3意义下
到最后所有动物的关系可以用树表示,d[i]表示节点i到当前fa[i]的距离,我们规定若d[x]+1=d[y](规定成-1也可以),代表x吃y
那么如果x、y同族,那么如果规定x当前祖先到y当前距离为的d[y]-d[x],这样x到y祖先距离为d[x](到自己当前祖先距离)+d[y]-d[x]=d[y]=y到y祖先距离,所以x\y同族
如果x吃y,那么就把x祖先到y祖先距离设为d[y]-d[x]-1,这样x到y祖先距离为d[x]+d[y]-d[x]-1=d[y]-1,则x吃y
#include<iostream>
#include<cstdio>
#include<cstring>
#define fr(i,s,t) for (i=s;i<=t;i++)
using namespace std;
int n,k,ans,fa[50001],d[50001];
int read(){
int x=0;char ch=0;
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x;
}
int fin(int x){
if (fa[x]==x) return x;
int f=fa[x];
fa[x]=fin(fa[x]);
d[x]=(d[f]+d[x]+3)%3;
return fa[x];
}
int main(){
n=read();k=read();
int i,t,x,y;
fr(i,1,n) fa[i]=i;
fr(i,1,k){
t=read();x=read();y=read();
if ((t==2&&x==y)||x>n||y>n){
ans++;
continue;
}
if (t==1){
if (fin(x)==fin(y)){
if (d[x]!=d[y]) ans++;
continue;
}
d[fa[x]]+=(d[y]-d[x]+3)%3;
fa[fa[x]]=fa[y];
}
else{
if (fin(x)==fin(y)){
if ((d[x]+1)%3!=d[y]) ans++;
continue;
}
d[fa[x]]=(d[y]-d[x]-1+3)%3;
fa[fa[x]]=fa[y];
}
}
printf("%d",ans);
}