传送门
不好意思呀, 这篇博客我就是转载的, 也就是这位大神的. 大家还是请看他的解释吧, 非常清楚易懂 …. 也可以当做是带权并查集的学习.
我觉得带权并查集就是要另开一个数组去记录当前这个点和根节点的关系, 然后还要推导路径压缩时的方程转移, 以及Un时的注意点, 注意到这些的话也就简单了吧?
AC Code
const int maxn = 5e4+5;
int fa[maxn], _rank[maxn];
int n;
void init() {
for (int i = 1 ; i <= n ; i ++) {
fa[i] = i;
_rank[i] = 0;
}
}
int Find(int x) {
if (fa[x] == x) return x;
else {
int tmp = fa[x];
fa[x] = Find(fa[x]);
_rank[x] = (_rank[tmp] + _rank[x]) % 3;
return fa[x];
}
}
void Un(int r, int x, int y) {
int fx = Find(x);
int fy = Find(y);
if (fx != fy) {
fa[fx] = fy;
_rank[fx] = (_rank[y] - _rank[x] + r + 3) % 3;
}
}
bool ok(int r, int u, int v) {
if (u > n || v > n) return false;
if (r && u == v) return false;
int fu = Find(u);
int fv = Find(v);
if (fu == fv) {
return (_rank[u] - _rank[v] + 3) % 3 == r;
}
else return true;
}
void solve()
{
int k;
scanf("%d%d", &n, &k);
int ans = 0; init();
for (int i = 1 ; i <= k ; i ++) {
int op, u, v;
scanf("%d%d%d", &op, &u, &v);
if (ok(--op, u, v)) Un(op, u, v);
else ans++;
}
printf("%d\n", ans);
}