码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 2818 Building Block(带权并查集)

时间:2015-04-24 12:37:49      阅读:120      评论:0      收藏:0      [点我收藏+]

标签:acm   并查集   

【题目链接】:Click here~~

【题意】:

给 n 块砖头,开始各为一堆,两种操作:

1、把 X 所在的那一堆箱子里的砖头放到 Y 所在的那一堆上面。

2、询问 X 下面有多少块砖。

【解题思路】:好像大家都叫它带权并查集,那为了方便,这里也这样叫吧,因为涉及前面的和后面的箱子个数,对应的查找操作,一开始想用结构体来写,在结构体里定义每个箱子的前驱和后继,每次输入的时候统计一下相应的前驱和后继的个数,后来发现不行,因为涉及到合并操作,比如说M 2 4 M 2 6连续出现两个2,用结构体是不容易实现的,这时候发挥并查集的效果了,在合并的时候分别更新 (1)Sum[i]=1;//i所在的箱子总数,(2)upsum[i]=0;//i下面箱子数,最后C a时直接输出upsum[a]

代码:

/*
Author:HRW
带权并查集
*/
#include <bits/stdc++.h>
using namespace std;
const int N=30005;
int father[N],Sum[N],upsum[N],n,m,a,b,T;
char ch[4];
int find(int x){
    if(x!=father[x]){
        int temp=find(father[x]);
        upsum[x]+=upsum[father[x]];
        father[x]=temp;
    }
    return father[x];
}
void Union(int a,int b)
{
    int pa=find(a);
    int pb=find(b);
    if(pa!=pb){
        upsum[pa]=Sum[pb];//合并pa下面pb的所有箱子
        Sum[pb]+=Sum[pa];//pb所在的堆的箱子总数
        father[pa]=pb;//合并根节点
    }
}
void init(){
    for(int i=0; i<N; i++)
    {
        father[i]=i;
        Sum[i]=1;//i所在的箱子总数
        upsum[i]=0;//i下面箱子数
    }
}
int main()
{
    while(scanf("%d",&T)!=EOF){
        init();
        for(int i=0; i<T; i++){
            scanf("%s",ch);
            if(ch[0]=='M'){
                scanf("%d%d",&a,&b);
                Union(a,b);
            }
            else{
                scanf("%d",&a);
                find(a);
                printf("%d\n",upsum[a]);
            }
        }
    }
    return 0;
}


HDU 2818 Building Block(带权并查集)

标签:acm   并查集   

原文地址:http://blog.csdn.net/u013050857/article/details/45243977

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!