洛谷 P1196 [NOI2002]银河英雄传说
Posted 俺是小程
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P1196 [NOI2002]银河英雄传说相关的知识,希望对你有一定的参考价值。
有很多人都把这道题讲得很详细了,我就不再重复了。
要总结的是,这可以看作一种“边带权”的并查集,对于这种并查集我们可以另开数组记录边上的关系,然后在find和unite的同时对关系进行维护。
于是此题中我们用一个 d 数组来记录当前战舰 到 这列战舰最前面的战舰 的战舰数量,
用一个 size 数组(在程序中为了避免关键字换成了siz)记录当前战舰后面跟了多少战舰(为了方便M操作时更新d)。
具体的维护方式参考代码。
1 #include <bits/stdc++.h>
2 using namespace std;
3 const int MAXT = 5e5 + 20;
4 const int MAXN = 3e4 + 20;
5
6 namespace ufs
7 {
8 int fa[MAXN], d[MAXN], siz[MAXN];
9
10 void init()
11 {
12 for(int i = 1; i <= MAXN; i++)
13 fa[i] = i, siz[i] = 1;
14 }
15
16 int get(int x)
17 {
18 if(x == fa[x]) return x;
19 int root = get(fa[x]);
20 d[x] += d[fa[x]];
21 return fa[x] = root;
22 }
23
24 inline void unite(int x, int y)
25 {
26 x = get(x), y = get(y);
27 fa[x] = y, d[x] = siz[y];
28 siz[y] += siz[x];
29 }
30 }
31
32
33 int main()
34 {
35 //freopen("p1196.txt", "r", stdin);
36 int T;
37 cin>>T;
38 using namespace ufs;
39 init();
40
41 char opt;int i, j;
42 while(T--)
43 {
44 scanf(" %c ", &opt);
45 if(opt == ‘M‘)
46 {
47 scanf("%d%d", &i, &j);
48 unite(i, j);
49 }
50 else
51 {
52 scanf("%d%d", &i, &j);
53 if(get(i) != get(j)) puts("-1");
54 else printf("%d\n", abs(d[i] - d[j]) - 1);
55 }
56 }
57 return 0;
58 }
注意有个细节:别忘了d[ x ]保存位于 x 之前的战舰数量,d[ y ]保存位于 y 之前的战舰数量,所以x,y之间的战舰数量应该是两者之差的绝对值再减1。
以上是关于洛谷 P1196 [NOI2002]银河英雄传说的主要内容,如果未能解决你的问题,请参考以下文章