- 题目链接:[NOI2002]银河英雄传说
- 题目思路: 根据题意,这道题明显要用带权并查集,我们用size数组表示一个集合内的容量,d[i]表示元素i之前的元素数量,我们可以在find()函数和合并过程中来维护d[]数组,具体解释见代码。
- 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using namespace std;
int sc() {
int xx = 0, ff = 1; char cch;
while (cch < '0' || cch > '9') {
if (cch == '-') ff = -1; cch = gc;
}
while (cch >= '0'&& cch <= '9') {
xx = (xx << 1) + (xx << 3) + (cch ^ '0'); cch = gc;
}
return xx * ff;
}
int t;
int fa[Maxn], size[Maxn], d[Maxn];
int find( int x) {
if (x == fa[x]) return x;
int xx = find( fa[x]);
d[x] += d[fa[x]];
return fa[x] = xx;
}
int aabs(int x) {
return x > 0 ? x : - x;
}
int main() {
t = sc();
for (int i = 1; i <= 30000; i++) { //赋初值,size数组为1
fa[i] = i;
size[i] = 1;
}
for (int i = 1; i <= t; i++) {
char c[2];
cin >> c[0];
int x = sc(), y = sc(); //一定要在合并前find(),因为find()函数不仅是找爸爸,还要维护d数组!!!
int xx = find( x);
int yy = find( y);
if (c[0] == 'M') {
// cout << xx << " "<< yy << endl;
fa[xx] = yy;
d[xx] = size[yy];
size[yy] += size[xx]; //注意我这样合并yy是父亲,则要把xx的元素数加到yy上
}
else {
// int x = sc(), y = sc();
// cout << fa[x] << " " << fa[y] << endl;
if(fa[x] == fa[y])
printf ("%d\n", aabs( d[x] - d[y]) - 1); //两艘战舰之间的数目不难推出为|d[x]-d[y]|-1
else
printf ("-1\n");
}
}
return 0;
}