根据两点到根节点的距离之差判断二者的关系
d[x]-d[y]%3==0表示x和y同类
d[x]-d[y]%3==1表示x吃y
d[x]-d[y]%3==1表示y吃x
如果x和y所在集合不同,则两者之间还未建立关系
维护节点到根节点距离的方法
d[x]表示x与父节点p[x]的距离,递归求出父节点p[x]到根节点的距离,则x到根节点的距离为d[x]+d[p[x]],然后将父节点p[x]更新为根节点
int find(int x){
if(p[x]!=x){
int t=find(p[x]);//更新p[x]到根节点的距离
d[x]+=d[p[x]];//维护到根节点的距离
p[x]=t;//更新父节点
}
return p[x];
}
判断x和y之间的关系
①如果x和y所在集合不同,则两者之间还未建立关系,建立关系时根据x和y的关系确定两者根节点的距离
②x和y所在同一集合
d[x]-d[y]%3==0表示x和y同类
d[x]-d[y]%3==1表示x吃y
int px=find(x),py=find(y);
//px==py表示x和y之间已经有联系(在同一集合中)
if(t==1){
if(px==py&&(d[x]-d[y])%3!=0) res++;
else if(px!=py){
p[px]=py;//x和y所在集合合并
d[px]=d[y]-d[x];//保持d[x]-d[y] %3==0
}
}else{
if(px==py&&(d[x]-d[y]-1)%3!=0) res++;
else if(px!=py){
p[px]=py;
d[px]=d[y]-d[x]+1;//保持d[x]-d[y]-1 %3==1
}
}
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int p[N],d[N];
int n,k,res;
int find(int x){
if(p[x]!=x){
int t=find(p[x]);//更新p[x]到根节点的距离
d[x]+=d[p[x]];//维护到根节点的距离
p[x]=t;//更新父节点
}
return p[x];
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++) p[i]=i;
while(k--){
int t,x,y;cin>>t>>x>>y;
if(x>n||y>n||t==2&&x==y){
res++;
continue;
}
int px=find(x),py=find(y);
//px==py表示x和y之间已经有联系(在同一集合中)
if(t==1){
if(px==py&&(d[x]-d[y])%3!=0) res++;
else if(px!=py){
p[px]=py;//x和y所在集合合并
d[px]=d[y]-d[x];//保持d[x]-d[y] %3==0
}
}else{
if(px==py&&(d[x]-d[y]-1)%3!=0) res++;
else if(px!=py){
p[px]=py;
d[px]=d[y]-d[x]+1;//保持d[x]-d[y]-1 %3==1
}
}
}
cout<<res;
}