洛谷 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;
}
posted @ 2021-08-21 17:11  Tartarus_li  阅读(21)  评论(0编辑  收藏  举报