zoukankan      html  css  js  c++  java
  • 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:
    ", ++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
    ",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 }
  • 相关阅读:
    [转]三五个人十来条枪 如何走出软件作坊成为开发正规军
    [转]asp.net页面字体变大问题总结
    [练手7]传值和传引用区别
    [练手3]选择排序
    [练手5]希尔排序
    oracle用select for update 中断后无法操作表的处理:杀掉SESSION
    [转]最省时管理法:让你一天随意
    [练手4]插入排序
    没有对“C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files”的写访问权限
    NUnit单元测试编写指南
  • 原文地址:https://www.cnblogs.com/usedrosee/p/4250974.html
Copyright © 2011-2022 走看看