需理清,两个数是否在一个集合。
两个数到祖先之间的距离%3后情况是否符合题意。
#include <bits/stdc++.h>
using namespace std;
const int N = 5e4 + 10;
int p[N],d[N];
int n,m;
int res;
int find(int x){
if(p[x] != x){
int t = find(p[x]);
d[x] += d[p[x]];//将两段连接起来
p[x] = t;
}
return p[x];
}
int main(){
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++){
p[i] = i;
}
while(m--){
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(x > n || y > n){//只要有一个动物的编号大于n,就为假话
res++;
}
else{
int root_x = find(x), root_y = find(y);
if(op == 1){//说明x和y是同类,则它们到祖先的距离%3应相于0
if(root_x == root_y && (d[x] - d[y]) % 3 ){//如果x和y的祖先相同,但它们距离之差%3不等于0,说明不是同类
res++;
}
else if(root_x != root_y){//假如祖先不同,将两个集合合并
p[root_x] = root_y;//x根节点的祖先起初为空,现在该祖先的祖先为y的祖先
d[root_x] = d[y] - d[x];//两个集合合并,(d[x] + ?) % 3 == d[y] % 3 -> ?= d[y] - d[x];
}
}
else{//如果x吃y,则d[x] - 1 - d[y]) % 3应等于0
if(root_x == root_y && (d[x] - 1 - d[y]) % 3){//如果x和y在同一个集合。
res++;
}
else if(root_x != root_y){//如果x和y不在同一个集合
p[root_x] = root_y;//x的祖先 的祖先从无变为y的祖先
d[root_x] = d[y] - d[x] + 1 ;//(d[x] - 1 + ?)%3 == d[y]%3 -> ? = d[y] - d[x] + 1;
}
}
}
}
cout << res << endl;
return 0;
}