lgP2024 食物链
动物王国中有3类动物A,B,C,构成食物链:A吃B,B吃C,C吃A。现有N个动物,每个动物都是A,B,C中的一种,有K个描述:
- 1 X Y,表示X和Y是同类
- 2 X Y,表示X吃Y
当一句话满足以下条件之一时,为假话,否则为真话。
- 与前面的话有冲突
- X或Y比N大
- X吃X
输出假话总数。
提示:种类并查集,对每个动物x,建立虚拟动物x1和x2,并且x吃x1,x2吃x。建虚拟节点是为了方便维护种类之间的关系。
#include <bits/stdc++.h>
using i64 = long long;
struct DSU {
std::vector<int> f;
DSU(int n) {
init(n);
}
void init(int n) {
f.resize(n);
std::iota(f.begin(), f.end(), 0);
}
int find(int x) {
while (x != f[x]) {
x = f[x] = f[f[x]];
}
return x;
}
void join(int x, int y) {
x = find(x);
y = find(y);
if (x != y) {
f[y] = x;
}
}
bool same(int x, int y) {
return find(x) == find(y);
}
};
void solve() {
int N, K;
std::cin >> N >> K;
DSU dsu(3*N);
auto predator = [&](int x) {
return x + 2 * N;
};
auto predatee = [&](int x) {
return x + 1 * N;
};
int ans = 0;
for (int i = 0; i < K; i++) {
int op, x, y;
std::cin >> op >> x >> y;
if (x > N || y > N) {
ans += 1;
continue;
}
x--, y--;
if (op == 1) {
if (dsu.same(x, predator(y)) || dsu.same(y, predator(x))) {
ans += 1;
} else {
dsu.join(x, y);
dsu.join(predator(x), predator(y));
dsu.join(predatee(x), predatee(y));
}
} else if (op == 2) {
if (dsu.same(x, predator(y))) {
;
} else if (dsu.same(x, y) || dsu.same(y, predator(x))) {
ans += 1;
} else {
dsu.join(x, predator(y));
dsu.join(predatee(x), y);
dsu.join(predator(x), predatee(y));
}
}
}
std::cout << ans << "\n";
}
int main() {
std::cin.tie(0)->sync_with_stdio(0);
int t = 1;
while (t--) solve();
return 0;
}