拓展域怎么搞,书上面肯定讲了。
在这一道题里面,有一个比较难搞的地方,那就是假话的关系是不能保存在并查集里面。
但是我们又需要用并查集判断某个生物拆成的三个点是否在同一集合内,而直接复制fa肯定会超时。
所以我们用一个栈来存储修改过的fa,然后跑并查集,如果是假话,那就把fa修改回原来的样子。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 5e4 + 10;
int n, k, fa[N], tp, a[N], b[N];
int findfa(int x) {
if (x == fa[x]) return x;
a[++tp] = x; b[tp] = fa[x];
return fa[x] = findfa(fa[x]);
}
void merge(int x, int y) {
int fx = findfa(x);
int fy = findfa(y);
if (fx != fy) {
a[++tp] = fx; b[tp] = fa[fx];
fa[fx] = fy;
}
}
int main() {
cin >> n >> k;
for (int i = 1; i <= 3 * n; i++) fa[i] = i;
int ans = 0;
for (int i = 1; i <= k; i++) {
int d, x, y;
scanf("%d%d%d", &d, &x, &y);
if (x > n || y > n) { ans++; continue; }
if (d == 2 && x == y) { ans++; continue; }
tp = 0;
if (d == 1) merge(x, y), merge(x + n, y + n), merge(x + n + n, y + n + n);
else merge(x, y + n), merge(x + n, y + n + n), merge(x + n + n, y);
if (findfa(x) == findfa(x + n) || findfa(x) == findfa(x + n + n) || findfa(x + n) == findfa(x + n + n) ||
findfa(y) == findfa(y + n) || findfa(y) == findfa(y + n + n) || findfa(y + n) == findfa(y + n + n)) {
ans++;
while (tp--) fa[a[tp]] = b[tp];
}
}
cout << ans << endl; return 0;
}