hdu2818(带权并查集)


题意:给出编号为1 - n堆的石头堆,初始每个石头堆中都有一块石头。然后有两个操作,M x y,表示的是将x石头堆堆在y石头堆上,C x 表示的是查询x石头堆下面有多少块石头。注意如果是移动第x堆的话,和他在一起的一起移动。如果是移动到第y堆,那么直接在第y堆最上面放,原来的不变。


PS:题意理解了许久许久。


思路:用两个数组,d数组表示的是在这堆下面的石头有多少块,num数组表示的是在这堆上面以及这堆的石头个数。

这样的话。num数组是向下更新,d数组是向上更新。

比如是M x y,那么将x整堆放在y堆上,首先y层最低层yy的上面的石头个数增大,num[yy] += num[xx],(xx = finds(x),yy = finds(y))。那么向上更新是通过finds函数对d数组进行更新。


#include<bits/stdc++.h>
using namespace std;
const int maxn = 200000 + 10;
int fa[maxn];
int d[maxn];
int num[maxn];
void Init()
{
    for(int i = 0; i < maxn; i ++)
        fa[i] = i,d[i] = 0,num[i] = 1;
}
int finds(int x)
{
   if(fa[x] != x)
   {
       int pre = fa[x];
       fa[x] = finds(fa[x]);
       d[x] += d[pre];
       return fa[x];
   }
   return x;
}
int main()
{
    int n;
    while( ~ scanf("%d",&n))
    {
        Init();
        for(int i = 1; i <= n; i ++)
        {
           char s[3];int x,y;
           scanf("%s%d",s,&x);
           int xx = finds(x);
           if(s[0] == 'M')
           {
               scanf("%d",&y);
               int yy = finds(y);
               if(xx != yy)
               {
                   fa[xx] = yy;
                   d[xx] = num[yy];
                   num[yy] += num[xx];
               }
           }
           else
           {
               printf("%d\n",d[x]);
           }
        }
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值