• hdu 2818Building Block


    Problem Description
    John are playing with blocks. There are N blocks (1 <= N <= 30000) numbered 1...N。Initially, there are N piles, and each pile contains one block. Then John do some operations P times (1 <= P <= 1000000). There are two kinds of operation:

    M X Y : Put the whole pile containing block X up to the pile containing Y. If X and Y are in the same pile, just ignore this command. 
    C X : Count the number of blocks under block X 

    You are request to find out the output for each C operation.
     
    Input
    The first line contains integer P. Then P lines follow, each of which contain an operation describe above.
     
    Output
    Output the count for each C operations in one line.
     
    Sample Input
    6 M 1 6 C 1 M 2 4 M 2 6 C 3 C 4
     
    Sample Output
    1 0 2
     
    这题算是一个简单的带权并查集的应用,问题中包含了两种操作,M操作,将包含x的block全部移到y上去,C操作询问在x下的block数是多少
    如果直接存储x下的block数会很麻烦,我们还不如求x上面的blocks总数,最后用它父节点所有的子节点数-x上面的blocks数-x本身就得到了
    要求的。对于带权并查集的应用,表示才刚开始学,所了解的也只有简单的几种。貌似这题跟黑书上的那个差不多。。
    View Code
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 const int N=30010;
     6 int father[N],rank[N],cnt[N];
     7 void init()
     8 {
     9     for(int i=0;i<=N-10;i++)
    10     {
    11         father[i]=i;
    12         rank[i]=1;
    13         cnt[i]=0;
    14     }
    15 }
    16 int find(int x)
    17 {
    18     if(x==father[x])
    19         return x;
    20     int t=father[x];
    21     father[x]=find(father[x]);
    22     cnt[x]+=cnt[t];
    23     return father[x];
    24 }
    25 void merge(int x,int y)
    26 {
    27     x=find(x),y=find(y);
    28     if(x==y)
    29         return ;
    30     father[y]=x;
    31     cnt[y]=rank[x];
    32     rank[x]+=rank[y];
    33 }
    34 int main()
    35 {
    36     int p,u,v;
    37     char cmd[2];
    38     while(scanf("%d",&p)!=EOF)
    39     {
    40         init();
    41         while(p--)
    42         {
    43             scanf("%s",cmd);
    44             if(cmd[0]=='M')
    45             {
    46                 scanf("%d%d",&u,&v);
    47                 merge(u,v);
    48             }
    49             else
    50             {
    51                 scanf("%d",&u);
    52                 v=find(u);
    53                 printf("%d\n",rank[v]-cnt[u]-1);
    54             }
    55         }
    56     }
    57     return 0;
    58 }
     
  • 相关阅读:
    c#常用正则表达式
    亲密接触Discuz!NT之架构篇:优良架构 方便网站整合与二次开发
    即时对话,在线对话,QQ,MSN,UC,popo
    C#事务处理
    正则表达式中的特殊字符
    9:38 2009729
    16:43 200981 缓解疲劳的七大唱片 免费短信
    复选框 全选
    9:05 2009721
    9:34 2009728
  • 原文地址:https://www.cnblogs.com/wilsonjuxta/p/2997209.html
Copyright © 2020-2023  润新知