您的位置:首页 > 产品设计 > UI/UE

HDU 2818 Building Block(带权并查集)

2015-04-24 11:17 330 查看
【题目链接】: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
,Sum
,upsum
,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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: