【ybtoj 高效进阶 3.1】 【并查集】 银河英雄传说
题目
解题思路
带权并查集
用dis记录当前节点到本集合第一个元素的距离
tot记录当前集合所含元素个数
查找
更新当前节点的距离
累加上父节点到根节点的距离
路径压缩
合并
x集合的第一个元素的距离变为y集合的元素个数
y集合元素个数累加上x集合的元素个数
询问
即两个元素到根节点的距离的差
代码
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
char c;
int n, x, y, fa[30010], dis[30010], tot[30010];
int find(int w) {
if (fa[w] == w)
return w;
int t = find(fa[w]);
dis[w] += dis[fa[w]];
return fa[w] = t;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= 30000; i++) {
fa[i] = i;
dis[i] = 0;
tot[i] = 1;
} //初始化
for (int i = 1; i <= n; i++) {
cin >> c;
scanf("%d%d", &x, &y);
int xx = find(x), yy = find(y);
if (c == 'M') {
dis[xx] = tot[yy];
tot[yy] += tot[xx];
fa[xx] = yy; //合并
} else if (xx != yy)
printf("-1\n");
else
printf("%d\n", abs(dis[x] - dis[y]) - 1); //输出差值,要减去自己
}
return 0;
}