题目链接
http://poj.org/problem?id=1182
分析
用带权并查集来维护每种动物之间吃与被吃的关系,
具体来说,每个节点指向其父亲的有向边的权值表示了这种关系,
0 0 0 表示是同类, 1 1 1 表示吃父亲, 2 2 2 表示被父亲吃,
确定某两点之间边的权值时要注意参与运算的各边的方向。
AC代码
#include <cstdio>
inline int read() {
int num = 0;
char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9')
num = num * 10 + c - '0', c = getchar();
return num;
}
const int maxn = 5e4 + 5;
int f[maxn], d[maxn];
int find(int x) {
if (x == f[x]) return x;
int root = find(f[x]);
d[x] = (d[x] + d[f[x]]) % 3;
return f[x] = root;
}
inline void merge(int a, int b, int s) {
int d1 = d[a], d2 = d[b];
a = find(a), b = find(b);
f[a] = b, d[a] = (s - d1 + d2 + 3) % 3;
}
int main() {
int n = read(), k = read(), cnt = 0;
for (int i = 1; i <= n; ++i) f[i] = i;
while (k--) {
int s = read(), x = read(), y = read();
if (x > n || y > n) ++cnt;
else if (s == 2 && x == y) ++cnt;
else if (find(x) != find(y)) merge(x, y, s - 1);
else if ((d[x] - d[y] + 3) % 3 != s - 1) ++cnt;
}
printf("%d", cnt);
return 0;
}