ybtoj并查集例题3银河英雄传说
Posted SSL_ZZL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ybtoj并查集例题3银河英雄传说相关的知识,希望对你有一定的参考价值。
Link
解题思路
设
n
u
m
[
i
]
num[i]
num[i]为 i为头的队伍有多少个点(就是代表一个集合里有多少点,因为i打头,所以i就为i集合的标记)
设
d
i
s
[
i
]
dis[i]
dis[i]为 i到
f
a
[
i
]
fa[i]
fa[i](即i的父节点)有多少士兵
并查集时,需维护
d
i
s
[
]
dis[]
dis[]
这就是带边权并查集 (吧)
Code
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int n, x, y, xx, yy, fa[30010], num[30010], dis[30010];
char c;
int find(int x) {
if (fa[x] == x)
return x;
int cnt = find(fa[x]);
dis[x] = dis[fa[x]] + dis[x]; //到新父亲的距离 = 到原父亲的距离 + 原父亲到 原父亲的父亲(也就是新父亲)的距离
fa[x] = cnt;
return fa[x];
}
int main() {
for (int i = 1; i <= 30000; i++)
fa[i] = i, num[i] = 1;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
cin >> c;
scanf("%d %d", &x, &y);
xx = find(x), yy = find(y);
if (c == 'M') {
fa[xx] = yy;
dis[xx] = num[yy]; //xx接到yy的队伍后,显而易见,xx到yy之间的士兵,就是yy原来后面有多少士兵
num[yy] += num[xx], num[xx] = 0; //依然显而易见;ps:因为xx不是头,所以xx无法作为此集合的标记
} else {
if (xx != yy)
printf("-1\\n");
else
printf("%d\\n", abs(dis[x] - dis[y]) - 1); //还是很显而易见吧(*^▽^*)
}
}
}
以上是关于ybtoj并查集例题3银河英雄传说的主要内容,如果未能解决你的问题,请参考以下文章