码迷,mamicode.com
首页 > 其他好文 > 详细

洛谷 P1196 [NOI2002]银河英雄传说

时间:2018-04-30 11:45:12      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:scanf   unit   一个   can   之间   its   for   max   style   

有很多人都把这道题讲得很详细了,我就不再重复了。

要总结的是,这可以看作一种“边带权”的并查集,对于这种并查集我们可以另开数组记录边上的关系,然后在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]银河英雄传说

标签:scanf   unit   一个   can   之间   its   for   max   style   

原文地址:https://www.cnblogs.com/wsmrxc/p/8973071.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!