1. 程式人生 > >hdu 3635 Dragon Balls

hdu 3635 Dragon Balls

lin one 路徑壓縮 -a void contain size expected exp

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:\n",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\n",k,city[k],time[c]);
			 }	 
		 	if(ch[0]=='T')
		 	{
		 		scanf("%d%d",&a,&b);
		 		merge(a,b);
			 }
			 	
		}
	}
	return 0;
}


hdu 3635 Dragon Balls