hdu2818 并查集

1、题目大意:
john 正在玩积木,有N个积木编号为1、、、N,分成N堆,每堆只包含一个积木,然后做P次操作,操作分为2种,
M X Y:把包含X的一堆放到包含Y的一堆上,如果XY同在一堆上,不做处理
C X:计算出X积木下边有多少个积木
每次遇到C操作,输出数量
遇到的问题:
第一个:数据的n有0的点,这个是数据的问题
第二个:有一个比较隐秘的bug,如果给出两块石头,且他们已经属于一个集合的话便不要做任何操作,我就是被这个数据卡住了,这里没注意的话在poj是能够ac的
思路:用a数组记录每一个块最上面的跟,用b数组记录最下面的根;用sum数组记录每个点到所在块最上面的根的距离,然后将给出的点point求出所在块的最下面的跟point1;sun[point1]-sum[point]就是所求答案;
代码:

#include<stdio.h>
int a[30005],b[30005],sum[30005],reg[30005];
int find(int tt) //求最上面的根,并计算tt点到根的距离;
{
    if(tt==a[tt])
        return tt;
    int t=a[tt];
    a[tt]=find(a[tt]);
    sum[tt]+=sum[t];
    return a[tt];
}
int find1(int tt) //求出tt最下面的根;
{
    if(tt!=b[tt])
    {
        b[tt]=find1(b[tt]);
    }
    return b[tt];
}
void sort(int x,int y,int za,int zb)  //求出y到x的距离
{
    a[y]=x;
    sum[y]+=reg[x];
    reg[x]=reg[x]+reg[y]; //reg函数记录每一个块点的数目,并且只有块最上面的点才记录;
    reg[y]=0;
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        int i,j;
        char c;
        int za,zb;
        for(i=0;i<30005;i++)//切记从0开始
        {
            a[i]=i;
            sum[i]=0;
            b[i]=i;
            reg[i]=1;
        }
        while(n--)
        {
            getchar();
            scanf("%c",&c);
            if(c=='M')
            {
                scanf("%d%d",&za,&zb);
                int x=find(za);
                int y=find(zb);
                if(x==y)  //如果给出的两个数在同一个块,则无需操作;
                    continue;
                int tx=find1(za);
                int ty=find1(zb);
                b[tx]=ty;
                sort(x,y,za,zb);
            }
            else
            {
                scanf("%d",&za);
                int zz=find1(za);
                int aa=find(za);
                int bb=find(zz);
                printf("%d\n",sum[zz]-sum[za]);
            }
        }
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值