题意:
中文题就不描述了;
思路:
带权并查集模板题;
加入一个数组r,表示这个点和它父节点的关系;
0表示同类,1表示父亲吃它,2表示它吃父亲;
每次需要更新和父亲之间的关系;
#include<cstdio>
#include<cstring>
const int N = 50005;
int p[N],r[N],n,k;
void init(int x) {
for(int i = 0; i <= x; i++) {
p[i] = i;
r[i] = 0;
}
}
int find_set(int x) {
if(x != p[x]) {
int fx = find_set(p[x]);
r[x] = (r[x] + r[p[x]]) % 3;
p[x] = fx;
}
return p[x];
}
bool Union(int x,int y,int rela) {
int px = find_set(x);
int py = find_set(y);
if(px == py) {
if(((r[y] - r[x] + 3) % 3) != rela)
return true;
else
return false;
}
p[py] = px;
r[py] = (r[x] - r[y] + rela + 3) % 3;
return false;
}
int main() {
int sum = 0;
scanf("%d%d",&n,&k);
init(n);
for(int i = 0; i < k; i++) {
int tmp,x,y;
scanf("%d%d%d",&tmp,&x,&y);
if(x > n|| y > n || (x == y && tmp == 2))
sum++;
else if(Union(x,y,tmp - 1))
sum++;
}
printf("%d\n",sum);
}