2015广工网络赛决赛-Problem E: 变形金刚(并查集)

题面:

Problem E: 变形金刚

Description

有一天Stubird买了一台变形金刚,店员说,这台变形金刚和其他那种骗小孩子的不一样 他真的能变形。 这台变形金刚有n个部件,他们能互相连接,组成机器人,当然,也可以变形。 但是有一天,The tesseract 的能量突然消失了,部件散落一地,当然有些部件还连接着。 现在你只有把部件全部连接起来,他就能变回原样,例如,有4个部件,1,2是连接的,3,4也是连接着的 ,你只需要把1和3连接起来(1,4或者2,3或者2,4)他就能变回原样啦。 他现在问你最少需要多少次连接才能把它变回原样?

Input

第一行一个T,表示有T个测试样例 接下来一个n和m(n<=10^5,0<=m<=10^5),n表示部件个数,m表示有多少个部件还连接着 下面m行,每行u,v表示部件u,v是连接着的。(1<=u,v<=n)

Output

求最小的连接次数

Sample Input

21 05 21 23 4

Sample Output

02



好久没写并查集,还错了两次 大哭


贴代码啦:

#include <iostream>
#include <cstdio>
using namespace std;
#define maxn 100005
struct node
{
	int parent;
	int rank;
}elem[maxn];
int n,m,t;
void Init()//初始化
{
	for(int i=1;i<=n;i++)//注意下标
	{
		elem[i].parent=i;
		elem[i].rank=1;
	}
}
int Find(int x)//寻找根节点
{
   int root,tmp;
   tmp=x;
   while(x!=elem[x].parent)
   {
   	 x=elem[x].parent;
   }
   root=x;
   x=tmp;
   while(x!=elem[x].parent)
   {
   	  tmp=elem[x].parent;
   	  elem[x].parent=root;
   	  x=tmp;
   }
   return root;	
}
void Union(int a,int b)//合并
{
	int x,y;
	x=Find(a);
	y=Find(b);
	if(elem[x].rank>=elem[y].rank)
	{
		elem[y].parent=elem[x].parent;
		elem[x].rank+=elem[y].rank;
	}
	else
	{
	    elem[x].parent=elem[y].parent;
		elem[y].rank+=elem[x].rank;
	}
}
int main()
{
	int x,y,a,b,cnt;
	scanf("%d",&t);
	while(t--)
	{
	    scanf("%d%d",&n,&m);
		Init();	
		for(int i=0;i<m;i++)
		{
			scanf("%d%d",&x,&y);
			a=Find(x);
			b=Find(y);
			if(a!=b)
			  Union(x,y);
		}
		cnt=0;
		for(int i=1;i<=n;i++)
		{
			if(elem[i].parent==i)//判断几个集合
			cnt++;
		}
		printf("%d\n",cnt-1); 
	} 
	return 0;
}


你可能感兴趣的:(并查集,简单题,广工网络赛)