POJ 2818 Building Block (并查集)(寻找一个元素下面有多少个元素)

来源:互联网 发布:怎么做淘宝网页设计 编辑:程序博客网 时间:2024/05/22 12:50
Building Block

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4611 Accepted Submission(s): 1433


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

题意:

使用并查集(路径压缩)实现,然后用num[X]表示X所在的那一堆总共多少个piles,ren[x]表示x之下有多少个piles。

 首先,每次操作我们合并两个集合(如果原来在同一集合中除外),num[X]是每次操作可以直接实现的,就是把两堆的数目相加,很容易(初始值为1)。那么当某次移动操作发生时,首先确定x所在的那一堆最底部的X以及y所在那一堆最底部的Y,那么ren[X]的数目就是另外一堆piles的总数num[Y],有了这个条件,在接下去的操作中,就可以根据FIND(x)递归去一边寻找根一边更新其他未知的num[x]。

代码:

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <string>using namespace std;const int maxx=30005;int par[maxx]; ///存放父亲结点int ren[maxx];///存放x下的元素的个数int num[maxx];///每堆上面的数目void init(){    for(int i=0; i<=maxx; i++)    {        par[i]=i;///初始化        ren[i]=0;/// 起初下面为0        num[i]=1; /// 每堆上面的数目为1    }}int find(int x){    if(par[x]==x)    {        return x;    }    else    {        int temp=find(par[x]);        ren[x]+=ren[par[x]];///更新每个结点下的数目(加上根节点下的数目)        par[x]=temp;        return par[x];    }}void unite(int a,int b){    a=find(a);    b=find(b);    if(a==b)        return ;        par[a]=b;        ren[a]=num[b];///更新a下面的数为b堆的数目        num[b]+=num[a];///b堆的数目更新为二者之和        num[a]=0;///合并后将a下的数目变为0}int main(){    int n;        scanf("%d",&n);         getchar();        init();        char s[5];        for(int i=1; i<=n; i++)        {            scanf("%s",s);            if(s[0]=='M')            {                int a,b;                scanf("%d%d",&a,&b);                    unite(a,b); ///合并            }            else  if(s[0]=='C')            {                int x;                scanf("%d",&x);                find(x);                printf("%d\n",ren[x]);            }        }    return 0;}



0 0
原创粉丝点击