并查集的应用。
题意略。
题解:用数组a来表示x节点与父节点的关系,Union操作和Find操作看代码。
a[x] = 0 父子同类
a[x] = 1 子吃父
a[x] = 2 父吃子
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 50005;
int set[MAXN], a[MAXN];
int f1[3][3] = {{0, 1, 2}, {2, 0, 1}, {1, 2, 0}};
int f2[3][3] = {{1, 2, 0}, {0, 1, 2}, {2, 0, 1}};
int find(int x) {
if (set[x] == x) return x;
int t = find(set[x]);
a[x] = (a[set[x]]+a[x])%3;
return set[x] = t;
}
void Union(int x, int y, int d) {
int fx = find(x);
int fy = find(y);
set[fx] = fy;
if (d == 1) a[fx] = f1[a[x]][a[y]];
else a[fx] = f2[a[x]][a[y]];
}
int main() {
int n, k, d, x, y;
int fx, fy;
int ans = 0;
scanf("%d %d", &n, &k);
memset(a, 0, sizeof(a));
for (int i=1; i<=n; i++) set[i] = i;
while ( k-- ) {
scanf("%d %d %d", &d, &x, &y);
if (x>n || y>n || (d==2 && x==y)) {
ans++;
continue;
}
fx = find(x);
fy = find(y);
if (fx == fy) {
if (d==1 && a[x]!=a[y]) {
ans++;
continue;
}
if (d==2 &&
((a[x]==0&&a[y]!=2)||(a[x]==1&&a[y]!=0)||(a[x]==2&&a[y]!=1))) {
ans++;
continue;
}
} else Union(x, y, d);
}
printf("%d\n", ans);
return 0;
}