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

hdu 2818 Building Block (带权并查集,很优美的题目)

2015-09-01 22:09 417 查看
[align=left]Problem Description[/align]

John are playing with blocks. There are N blocks (1 <= N <= 30000) numbered 1...N。Initially, there are N piles, and each pile contains one block. Then John do some operations P times (1 <= P <= 1000000). There are two kinds of operation:

M X Y : Put the whole pile containing block X up to the pile containing Y. If X and Y are in the same pile, just ignore this command.
C X : Count the number of blocks under block X

You are request to find out the output for each C operation.


[align=left]Input[/align]

The first line contains integer P. Then P lines follow, each of which contain an operation describe above.


[align=left]Output[/align]

Output the count for each C operations in one line.


[align=left]Sample Input[/align]

6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4


[align=left]Sample Output[/align]

1
0
2


[align=left]Source[/align]
2009 Multi-University Training Contest 1 - Host by TJU

题目大意:有N个piles(按序编号),每次有两种操作:



M x y表示把x所在的那一堆全部移到y所在的那一堆



C x 询问在x之下有多少个方块



解决方法:使用并查集(路径压缩)实现,然后用count[X]表示X所在的那一堆总共多少个piles,under[x]表示x之下有多少个piles。



首先,每次操作我们合并两个集合(如果原来在同一集合中除外),count[X]是每次操作可以直接实现的,就是把两堆的数目相加,很容易(初始值为1)。那么当某次移动操作发生时,首先确定x所在的那一堆最底部的X以及y所在那一堆最底部的Y,那么under[X]的数目就是另外一堆piles的总数count[Y],有了这个条件,在接下去的操作中,就可以根据FIND(x)递归去一边寻找根一边更新其他未知的under[x]。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 30006
int fa
;
int under
;//下边的个数
int cnt
;//所在堆的堆个数
void init(){
for(int i=0;i<N;i++){
fa[i]=i;
under[i]=0;
cnt[i]=1;
}
}
int find(int son){
if(fa[son]!=son){
int t=find(fa[son]);
under[son]+=under[fa[son]];
fa[son]=t;
}
return fa[son];
//return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y){
int root1=find(x);
int root2=find(y);
if(root1==root2)return;
under[root1]=cnt[root2];
cnt[root2]+=cnt[root1];
fa[root1]=root2;
}
int main()
{
int n;
while(scanf("%d",&n)==1){
init();
char s[3];
int x,y;
for(int i=0;i<n;i++){
scanf("%s",s);
if(s[0]=='M'){
scanf("%d%d",&x,&y);
merge(x,y);
}
else{
scanf("%d",&x);
find(x);
printf("%d\n",under[x]);
}
}
}
return 0;
}


View Code

[align=left]Recommend[/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: