UVA 11987 Almost Union-Find (并查集+技巧)
题目链接:https://www.luogu.com.cn/problem/UVA11987
唯一需要考虑的就是操作二,将某元素从一个并查集移动到另一个并查集中
建立一个新节点代表该元素,将原来的元素留在原位,原来的并查集减掉,新的并查集加上即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100010;
int n, m, tot;
int fa[maxn], cnt[maxn], sum[maxn], id[maxn];
int find(int x){
return (fa[x] == x) ? x : find(fa[x]);
}
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
while(scanf("%d%d", &n, &m) != EOF){
tot = n;
for(int i = 1 ; i <= n ; ++i) fa[i] = i, cnt[i] = 1, sum[i] = i, id[i] = i;
int op, p, q;
for(int i = 1 ; i <= m ; ++i){
scanf("%d", &op);
if(op == 1){
scanf("%d%d", &p, &q);
int u = find(id[p]), v = find(id[q]);
if(u != v){
fa[u] = v;
cnt[v] += cnt[u];
sum[v] += sum[u];
}
} else if(op == 2){
scanf("%d%d", &p, &q);
int u = find(id[p]), v = find(id[q]);
if(u != v){
id[p] = ++tot;
cnt[u]--;
sum[u] -= p;
fa[id[p]] = v;
++cnt[v];
sum[v] += p;
}
} else{
scanf("%d", &p);
int u = find(id[p]);
printf("%d %d\n", cnt[u], sum[u]);
}
}
}
return 0;
}