poj 1988 Cube Stacking(加权并查集 )

相比无限种类并查集我更认为这题是加权并查集(好吧种类并查集就是加权的一种,不要吐槽了~),这题也是我刷并查集专题的结束。以后博客如果再更并查集就是并查集的难题了233~不过希望我能解出并查集的难题并整理出题解分享给大家。。。

题意:就是说两个农民A和B,面前有n(1<=n<=30000)个相同木块(每个木块都都序号1~n),移动p次(1<=p<=10,000)(次数比较多,我因为这个写的另外两个算法超时了),A让B移动木块。有两种操作
M x y 将包换 x的木块移动到包含y的木块上面。
C x 计算编号是x的 木块下面有多少个木块

思路: 并查集,把放在最下面的一个木块认为是根节点,然后其他放在上面的都用gp标记一下,表示下面有多少个木块(gp[i]表示的是编号是i的木块下面有多少个木块),根节点的gp为0,如果两棵树合并就用find的状态压缩,先递归,再维护(这个在前面几个并查集里详细讲了~),再用a数组存放这个以i为根节点是树中下一个叶子下面有多少个木块,a数组初始化为什么为1比较方便,可以模拟体会一下~

#include<cstdio>
#include<cstring>
#define LOCAL
using namespace std;
int gp[30100],pa[30100],max,min,a[30100];

inline void init(){
    for(int i = 0; i < 30050; i++){
        pa[i] = i;
        gp[i] = 0;
        a[i] = 1;
    } 
}

int find(int x){
    int fa;
    if(x != pa[x]){ 
       int tmp = pa[x];   
       pa[x] = find(pa[x]);
           gp[x] = gp[tmp] + gp[x];//维护树,加权并查集的写发
    }
    return pa[x];
}

void unite(int x,int y){
    int fx = find(x);
    int fy = find(y);
    if(fx != fy){
        pa[fx] = fy;
        gp[fx] = a[fy];
        a[fy] += a[fx]; 
    }
}

int main(){
/*#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif*/ 
    int p,x,y;
    char c;
    scanf("%d",&p);
    init();
    max = -1;
    min = 10010;
    while(p--){
        getchar();
        scanf("%c",&c);
        if(c=='C') {
            scanf("%d",&x);
            find(x);
            printf("%d\n",gp[x]);
        }
        else if(c=='M'){
            scanf("%d%d",&x,&y);
            unite(x,y);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值