并查集的应用。
题意略。
题解:用数组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; }