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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值