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

hdoj 2818 Building Block(加权并查集)

2016-07-22 20:10 429 查看


Building Block

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 4856    Accepted Submission(s): 1505


Problem Description

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.

 

Input

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

 

Output

Output the count for each C operations in one line.

 

Sample Input

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

 

Sample Output

1
0
2

 

Source

2009 Multi-University Training
Contest 1 - Host by TJU

 

题意:john 正在玩积木,有N个积木编号为1、、、N,分成N堆,每堆只包含一个积木,然后做P次操作,操作分为2种,
M X Y:把包含X的一堆放到包含Y的一堆上,如果XY同在一堆上,不做处理
C X:计算出X积木下边有多少个积木
每次遇到C操作,输出数量



 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 30005;
int pre[maxn], count[maxn], under[maxn];    //count[i]记录i所在堆的木块总数,under记录i木块下方的木块数量
int Find(int x)
{
if(pre[x] == x) return x;
else
{
int t = Find(pre[x]);   //递归找到根
under[x] += under[pre[x]];  //从根下第一个节点开始回溯更新节点的under数,
//每个节点的under数即为原来的加上根节点在join时更新的under,
//即加上b堆的总数,因为b堆都在a下面
pre[x] = t;
return t;
}
}
//join只把两个堆连上,即将y的根节点作为x的根节点的父节点
void join(int x, int y)
{
int a = Find(x), b = Find(y);   //各一次Find,会x,y到根节点的under更新并压缩路径。
if(a != b)
{
under[a] = count[b];    //a接到了b上,under[a]即为b的总数
count[b] += count[a];   //同时更新b的总数
pre[a] = b;
}
}
int main(void)
{
int n;
while(cin >> n)
{
for(int i = 0; i < maxn; i++) { pre[i] = i; under[i] = 0; count[i] = 1; }
while(n--)
{
char cmd;
cin >> cmd;
if(cmd == 'M')
{
int a, b;
scanf("%d%d", &a, &b);
join(a, b);
}
else
{
int a;
scanf("%d", &a);
Find(a);<span style="white-space:pre">		 //还需自己把a到它的根节点的每个节点的under更新一下</span>
printf("%d\n", under[a]);
}
}
}
return 0;
}



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