SPOJ IAPCR2F 【并查集】

思路:

利用并查集/DFS都可以处理连通问题。

PS:注意Find()查找值和pre[]值的区别。

#include<bits/stdc++.h>
using namespace std;

const int N=1e3+10;
int val[N];
int pre[N],n,m;
vector<int>xs,ans;

int Find(int x)
{
	int r=x;
	while(pre[r]!=r)
		r=pre[r];
	int i=x,j;
	while(pre[i]!=r)
	{
		j=pre[i];
		pre[i]=r;
		i=j;
	}
	return r;
}

int main()
{
	int T,cas=1,x,y;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&val[i]);
			pre[i]=i;
		}
		while(m--)
		{
			scanf("%d%d",&x,&y);
			x=Find(x);
			y=Find(y);
			if(x!=y)
				pre[x]=y;
		}
		xs.clear();
		ans.clear();
		for(int i=1;i<=n;i++)
			if(pre[i]==i) xs.push_back(i);
		int sz=xs.size();
		for(int i=0;i<sz;i++)
		{
			int sum=0;
			for(int j=1;j<=n;j++)
				if(Find(j)==xs[i])
					sum+=val[j];
			ans.push_back(sum);
		}
		sort(ans.begin(),ans.end());
		sz=ans.size();
		printf("Case %d: %d\n",cas++,sz);
		for(int i=0;i<sz;i++)
		{
			if(i) printf(" ");
			printf("%d",ans[i]);
		}
		puts("");
	}
	return 0;
}


posted @ 2017-03-08 23:23  see_you_later  阅读(180)  评论(0编辑  收藏  举报