杭电 2818 并查集的应用

       是一道关于并查集的题,每个结点处多了两个属性,一个是该点以上有多少个点,即up属性。另一个是该点下面有多少个点,即down属性,查找和合并操作时,把up和down属性也一起更新就可以了。。。。。题目:

Building Block

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1061    Accepted Submission(s): 311


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
 

ac代码:

#include <iostream>
#include <cstdio>
using namespace std;
#define M 30010
int up[M],down[M],p[M];
void init(){
	for(int i=0;i<M;++i){
	  up[i]=0;
	  down[i]=1;
	  p[i]=i;
	}
}
int find(int x){
  int t=p[x];
  if(t!=x){
	p[x]=find(t);
    up[x]+=up[t];//更新该点到父节点的距离
  }
  return p[x];
}
void unionset(int x,int y){
  int px=find(x);
  int py=find(y);
  if(px!=py){
    p[py]=px;
	up[py]=down[px];
	down[px]+=down[py];
  }
}
void count(int x){
  int root=find(x);//更新x点到最远祖先的距离
  printf("%d\n",down[root]-up[x]-1);
}
int main(){
  //freopen("1.txt","r",stdin);
  int numcase;
  while(~scanf("%d",&numcase)){
	init();
    char que;
	int x,y;
	while(numcase--){
	  cin>>que;
	  if(que=='M'){
	    scanf("%d%d",&x,&y);
		unionset(x,y);
	  }else{
	    scanf("%d",&x);
		count(x);
	  }
	}
  }
  return 0;
}


你可能感兴趣的:(c,Integer,input,UP,each,output)