洛谷 P1196 银河英雄传说 (带权并查集)
题目链接:https://www.luogu.com.cn/problem/P1196
带权并查集维护 \(d[u]\) 表示 \(u\) 到父节点的距离,路径压缩时更新(压缩后父节点变为根),当前集合的根到合并到的集合的根的距离根据题目而定,有时要维护信息来更新,如本题要维护集合大小
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 30010;
int T, n;
int par[maxn], d[maxn], c[maxn];
int find(int x){
if(par[x] != x){
int rt = find(par[x]);
d[x] += d[par[x]];
c[x] = c[rt];
return par[x] = rt;
} else return 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(){
scanf("%d", &T);
for(int i = 1 ; i <= 30000 ; ++i) par[i] = i, d[i] = 0, c[i] = 1;
char op[10];
int u, v;
for(int i = 1 ; i <= T ; ++i){
scanf("%s", op);
scanf("%d%d", &u, &v);
if(op[0] == 'M'){
u = find(u), v = find(v);
par[u] = v;
d[u] = c[v];
c[v] += c[u];
} else{
int ru = find(u), rv = find(v);
if(ru != rv){
printf("-1\n");
} else{
printf("%d\n", abs(d[u] - d[v])-1);
}
}
}
return 0;
}