hdu 3635 Dragon Balls 并查集

题目大意:初始时,有n个龙珠,编号从1到n,分别对应的放在编号从1到n的城市中。现在有两种操作:

T A B,表示把A球所在城市全部的龙珠全部转移到B城市。(第一次时,因为A球所在的城市只有一个球,所以只移动1个,如果有多个,则全部移动)。

Q A,表示查询A。要求得到的信息分别是:A现在所在的城市,A所在城市的龙珠数目,A转移到该城市移动的次数(如果没有移动就输出0)

这道题主要的问题是转移次数,初始时每个龙珠的转移次数为0,若将a移到b,则将a所在集合的根结点加一,表示整个a集合都移动了一次,如果查找某个节点x的移动次数,则在路径压缩时需要加上它父节点的移动次数,递归解决。

#include <stdio.h>
#include <string.h>
#define maxn 10200
int p[maxn],tran[maxn],cap[maxn];
int t;

int find(int x)
{
	int a;
	if(p[x]==x) return x;
	else 
	{
		a=find(p[x]);
		tran[x]+=tran[p[x]];
		p[x]=a;
		return p[x];
	}
}

void link(int a,int b)
{
	int x,y;
	x=find(a);
	y=find(b);
	if(x!=y)
	{
		p[x]=y;
		tran[x]++;
		cap[y]+=cap[x];
		cap[x]=0;
	}
}

int main()
{
	int i,x,y;
	int sum=0;
	int n,q;
	char a;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&q);
		for(i=1;i<=n;i++) { p[i]=i;cap[i]=1;tran[i]=0; }
		sum++;
		printf("Case %d:
",sum);
		for(i=1;i<=q;i++)
		{
			getchar();
			scanf("%c",&a);
			if(a=='T')
			{
				scanf("%d%d",&x,&y);
				link(x,y);
			}
			else
			{
				scanf("%d",&x);
				int ans=find(x);
				printf("%d %d %d
",ans,cap[p[x]],tran[x]);
			}
		}
	}
	return 0;
}


 

原文地址:https://www.cnblogs.com/vermouth/p/3710188.html