【HDU 3635】 Dragon balls (带权并查集,点维护)

传送门

题目大意:有n个龙蛋,分别坐落在n个城市。现在有m个操作。操作分为T,Q。对于T:给出x,y,把x所在的城市中的蛋全部移到y所在城市去。对于Q:给出x,我们需要输出x所在的城市的编号,以及这个城市中的龙蛋数量,还有x移动了的次数

Solution:只需维护三个值:所在城市,龙蛋数量,移动次数。我们用father[i]代表i所在城市编号,cnt[i]代表i城市的龙蛋数量,times[i]代表i移动了多少次。

考虑如何维护:对于father,只需要普通的并查集操作;对于cnt,在每次T操作后,动态更新;对于times,由于需要每个节点的移动次数,如果采用O(n)维护是显然会TLE的,所以考虑在路径压缩时顺便更新即可。

#include<bits/stdc++.h>
#define N 10005
using namespace std;
int T,n,q,father[N],times[N],cnt[N];	//father[i]:第i个蛋属于哪个城市 times[i]:第i颗蛋移动次数 cnt[i]:第i个城市有多少个蛋 
inline int getfather(int x)
{
	if(father[x]==x)	return x;
	int fa=father[x];
	father[x]=getfather(father[x]);//其实每个根结点都是最多移动一次的
	times[x]+=times[fa];
	return father[x];
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL); 
	cin>>T;
	for(int i=1;i<=T;i++)
	{
		cout<<"Case "<<i<<":"<<'\n'; 
		cin>>n>>q;
		for(int i=1;i<=n;i++){
			father[i]=i;
			times[i]=0;
			cnt[i]=1;
		}
		while(q--)
		{
			char opt;
			int x,y;
			cin>>opt;
			if(opt=='T')
			{
				cin>>x>>y;
				int ax=getfather(x);
				int bx=getfather(y);
				if(ax!=bx)
				{
					father[ax]=bx;
					cnt[bx]+=cnt[ax];
					times[ax]++;
				}
			}
			
			if(opt=='Q')
			{
				cin>>x;
				int ax=getfather(x);
				cout<<ax<<" "<<cnt[ax]<<" "<<times[x]<<'\n';
			}
		}

		 
	}
	return 0;
}
posted @ 2018-07-29 11:28  Patrickpwq  阅读(70)  评论(0编辑  收藏  举报