带扩展域和带边权并查集
P2024 [NOI2001] 食物链
AcWing 240. 食物链(带扩展域 和 带边权 并查集 两种做法)
带拓展域的并查集
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e4 + 10;
int n, m;
int p[N * 5];
int find(int x) {
if (p[x] != x) {
p[x] = find(p[x]);
}
return p[x];
}
int cnt;
//带 扩展域 的并查集
signed main() {
cin >> n >> m;
for (int i = 1; i < N * 5; i++) p[i] = i;
for (int i = 1; i <= m; i++) {
int op, x, y;
cin >> op >> x >> y;
if (x > n || y > n) {
cnt++;
continue;
}
//同类?
if (op == 1) {
if (x == y) continue;
if (find(x) == find(y + N) || find(x + N) == find(y)) {
cnt++;
continue;
}
p[find(x)] = find(y);
p[find(x + N)] = find(y + N);
p[find(x + N * 2)] = find(y + N * 2);
}
//吃?
else {
if (x == y) {
cnt++;
continue;
}
if (find(x + N) == find(y) || find(x) == find(y)) {
cnt++;
continue;
}
p[find(x)] = find(y + N);
p[find(x + N)] = find(y + N * 2);
p[find(x + N * 2)] = find(y);
}
}
cout << cnt << '\n';
}
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e5 + 10;
int n, m;
int cnt;
int p[N];
int d[N];
//带边权并查集
int find(int x) {
if (p[x] != x) {
int t = find(p[x]);
d[x] += d[p[x]];
p[x] = t;
}
return p[x];
}
signed main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) p[i] = i;
int ans = 0;
for (int i = 1; i <= m; i++) {
int op, x, y;
cin >> op >> x >> y;
if (x > n || y > n) {
ans++;
continue;
}
int a = find(x), b = find(y);
if (op == 1) {
if (a == b && (d[x] - d[y]) % 3) {
ans++;
} else if (a != b) {
p[a] = b;
d[a] = d[y] - d[x];
}
} else {
if (a == b && (d[x] - d[y] - 1) % 3) {
ans++;
} else if (a != b) {
p[a] = b;
d[a] = d[y] + 1 - d[x];
}
}
}
cout << ans << '\n';
}
P1196 [NOI2002] 银河英雄传说
带权并查集模板
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 10;
int n, m;
//father数组,路径,队列长度
int p[N], d[N], si[N];
int find(int x) {
if (p[x] != x) {
int t = find(p[x]);
d[x] += d[p[x]];
p[x] = t;
}
return p[x];
}
signed main() {
for (int i = 1; i < N; i++) p[i] = i, si[i] = 1;
int T;
cin >> T;
while (T--) {
char op;
int x, y;
cin >> op >> x >> y;
if (op == 'M') {
int a = find(x), b = find(y);
// 需要判断,防止size数组重复加
if (a != b) {
p[a] = b;
d[a] = si[b];
si[b] += si[a];
}
} else {
int a = find(x), b = find(y);
// cout << a << ' ' << b << '\n';
// cout << d[x] << ' ' << d[y] << '\n';
if (a != b) cout << -1 << '\n';
else {
if (d[x] != d[y])
cout << abs(d[x] - d[y]) - 1 << '\n';
else
cout << 0 << '\n';
}
}
}
}