hdu 3635 Dragon Balls 并查集

推荐题解:http://www.cppblog.com/cxiaojia/archive/2011/11/04/nyoj431.html

思路:看懂题意后就知道用并查集了。询问的前两个问题都很好解决,有点难度的是第三个问题,龙珠被移动的次数。我用rnk数组统计每颗龙珠移动的次数,路径压缩后,每颗龙珠的父亲就是它所在的城市,如果这颗龙珠所在的城市所有的龙珠被移走的话,这座城市变成一座空城市,所以不会有龙珠再被移动到这座城市,就是说一座城市只能转移一次,假设a所在的城市的所有龙珠移动到了b,合并的时候统计这座城市移动的次数,那么统计龙珠的时候,只要统计它的父亲它的祖父一直到它的老祖,每个长辈的rnk和就是这颗龙珠的移动次数。所以在merge的时候让它父亲的rnk++,Find的时候让它遍历到根节点每次都加上一个长辈的rnk。写完后会感觉到,就是一个体的并查集。


 

注意:printf的先从右向左计算  再输出,右边的数受左边的数影响时容易出错。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<string>
 6 #include<queue>
 7 #include<algorithm>
 8 #include<map>
 9 #include<iomanip>
10 #include<climits>
11 #define INF 1e11
12 #define MAXN 10010 
13 using namespace std;
14 
15 #define _min(a,b) (((a)<(b))?((a):(b)))
16 //适用于正负整数
17 template <class T>
18 inline bool scan_d(T &ret) {
19     char c; int sgn;
20     if (c = getchar(), c == EOF) return 0; //EOF
21     while (c != '-' && (c<'0' || c>'9')) c = getchar();
22     sgn = (c == '-') ? -1 : 1;
23     ret = (c == '-') ? 0 : (c - '0');
24     while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
25     ret *= sgn;
26     return 1;
27 }
28 
29 int ball_num[MAXN];
30 int fa[MAXN];
31 int rnk[MAXN];
32 int a, b;
33 int T, n, m, k;
34 char ch;
35 
36 int find(int x) {
37     if (fa[x] == x) return x;
38     int t = fa[x];
39     fa[x] = find(fa[x]);
40     rnk[x] += rnk[t];
41     return fa[x];
42 }
43 
44 void init(int n)
45 {
46     for (int i = 1; i <= n; ++i) {
47         ball_num[i] = 1;
48         fa[i] = i;
49         rnk[i] = 0;
50     }
51 }
52 
53 bool merge(int a, int b)
54 {
55     int x = find(a);
56     int y = find(b);
57     if (x == y) return false;
58     else {
59         ball_num[y] += ball_num[x];
60         ball_num[x] = 0;
61         fa[x] = fa[y];
62         rnk[x] = 1;
63     }
64     return true;
65 }
66 
67 void process()
68 {
69     printf("Case %d:\n", ++k);
70     scan_d(n); scan_d(m);
71     init(n);
72     for (int i = 0; i < m; ++i) {
73         cin >> ch;
74         if (ch == 'T') {
75             scan_d(a); scan_d(b);
76             merge(a, b);
77         }
78         else {
79             scan_d(a);
80             b = find(a);
81             printf("%d %d %d\n",b, ball_num[b], rnk[a]);
82         }
83     }
84 }
85 
86 int main()
87 {
88     scan_d(T);
89     while (T--)
90         process();
91     //system("pause");
92     return 0;
93 }

 

转载于:https://www.cnblogs.com/usedrosee/p/4250974.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值