hdu 3635 Dragon Balls

Dragon Balls

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


Problem Description
Five hundred years later, the number of dragon balls will increase unexpectedly, so it's too difficult for Monkey King(WuKong) to gather all of the dragon balls together.

His country has N cities and there are exactly N dragon balls in the world. At first, for the ith dragon ball, the sacred dragon will puts it in the ith city. Through long years, some cities' dragon ball(s) would be transported to other cities. To save physical strength WuKong plans to take Flying Nimbus Cloud, a magical flying cloud to gather dragon balls.
Every time WuKong will collect the information of one dragon ball, he will ask you the information of that ball. You must tell him which city the ball is located and how many dragon balls are there in that city, you also need to tell him how many times the ball has been transported so far.
 

Input
The first line of the input is a single positive integer T(0 < T <= 100).
For each case, the first line contains two integers: N and Q (2 < N <= 10000 , 2 < Q <= 10000).
Each of the following Q lines contains either a fact or a question as the follow format:
  T A B : All the dragon balls which are in the same city with A have been transported to the city the Bth ball in. You can assume that the two cities are different.
  Q A : WuKong want to know X (the id of the city Ath ball is in), Y (the count of balls in Xth city) and Z (the tranporting times of the Ath ball). (1 <= A, B <= N)
 

Output
For each test case, output the test case number formated as sample output. Then for each query, output a line with three integers X Y Z saparated by a blank space.
 

Sample Input
2 3 3 T 1 2 T 3 2 Q 2 3 4 T 1 2 Q 1 T 1 3 Q 1
 

Sample Output
Case 1: 2 3 0 Case 2: 2 2 1

3 3 2

题意:题意:刚開始每一个city都有一个相应编号的球,如今给出2个命令,一个是T A B 将A所在的城市里的全部球转移到B球所在的城市,  一个是C A 要求输出A球所在的城市的编号和该城市共同拥有多少个球,以及A球被转移的次数。

   思路:首先这里刚開始球的编号和城市的编号一一相应,要想到并查集的方法,其次对于T命令的操作就是合并A和B的城市,  仅仅要将统计城市球数的数组更新一下就可以,并对A城市的根节点所在的球的转移次数设置为1 ,  由于显然这个根节点所相应的球是第一次被转移,难点在于其它的球的转移次数须要依据这个根节点的转移次数来求出。

 关键就是路径压缩了,要想求某个球的转移次数,须要对它进行路径的更新,  一直更新到它的根节点,依据根节点的转移次数为1,回溯递推出要求的球的转移次数。  加权并查集,,递归的过程好难理解。  2015,7,23

#include<stdio.h>
#include<string.h>
#define M 10100
int f[M],time[M],city[M];//分别存放,父节点。转移次数,城市里边的珠子总数 
void init()
{
	for(int i=0;i<M;i++){
		f[i]=i;//父节点初始化为自己 
		city[i]=1;//開始的时候每一个城市有一个球 
		time[i]=0;
	}
}
int find(int k)
{
	if(f[k]!=k)
	{
		int temp=find(f[k]);//找到根节点 
		time[k]+=time[f[k]];//子节点的转移次数加上父节点的转移次数 
		f[k]=temp;//压缩路径,父节点直接指向根节点 
	}
	return f[k];
 } 
void merge(int a,int b)
{
	int x=find(a);
	int y=find(b);
	if(x!=y)
	{
		f[x]=y;
		time[x]=1;//第一次转移 
		city[y]+=city[x];
		city[x]=0;
	}
}
int main()
{
	int t,v=1,i,a,b,c,n,m;
	char ch[5];
	scanf("%d",&t);
	while(t--)
	{
		init();
		printf("Case %d:
",v++);
		scanf("%d%d",&n,&m);
		for(i=0;i<m;i++)
		{
		 	scanf("%s",ch);
		 	if(ch[0]=='Q')
			 {
			 	int k;
			 	scanf("%d",&c);
			 	k=find(c);
			 	printf("%d %d %d
",k,city[k],time[c]);
			 }	 
		 	if(ch[0]=='T')
		 	{
		 		scanf("%d%d",&a,&b);
		 		merge(a,b);
			 }
			 	
		}
	}
	return 0;
}


原文地址:https://www.cnblogs.com/yutingliuyl/p/7297410.html