好朋友【并查集】

一、问题描述

        有一个叫做“数码世界”奇异空间,在数码世界里生活着许许多多的数码宝贝,其中有些数码宝贝之间可能是好朋友,并且数码宝贝世界有两条不成文的规定:
        第一,数码宝贝A和数码宝贝B是好朋友等价于数码宝贝B与数码宝贝A是好朋友
        第二,如果数码宝贝A和数码宝贝C是好朋友,而数码宝贝B和数码宝贝C也是好朋友,那么A和B也是好朋友,现在给出这些数码宝贝中所有好朋友的信息,问:可以把这些数码宝贝分成多少组,满足每组中的任意两个数码宝贝都是好朋友,而且任意两组之间的数码宝贝都不是好朋友

输入格式

        输入的第一行给右两个正整数n(n<=100)和m(m<=100),分别表示数码宝贝的个数和好朋友的组数,其中数码宝贝编号为1~n。
       接下来有m行,每行两个正整数a和b,表示数码宝贝a和数码宝贝b是好朋友。

输出格式

        输出一个整数,表示这些数码宝贝可以分成的组数

样例输入1

4 2
1 4
2 3

样例输出1

2

样例输入1

7 5
1 2
2 3
3 1
1 4
5 6

样例输出1

3

二、算法实现

1、用一个全局数组,来标记每个元素是不是老祖宗(根)。

2、用一个数组,下标表示元素,数组单元存的内容表示对应元素(下标)的father。

#include<cstdio>
const int maxn=110;

int father[maxn];  //全局变量 
bool isRoot[maxn];  //全局 

int findFather(int x)   //寻祖 
{
	int a=x;
	while(x!=father[x])
	{
		x=father[x];
	}
	while(a!=father[a])
	{
		int z=a;
		a=father[a];
		father[z]=x;
	}
	return x;
}

void Union(int a,int b)   //合并 
{
	int faA=findFather(a);
	int faB=findFather(b);
	if(faA!=faB)
	{
		father[faA]=faB;
	}
}

void init(int n)   //初始化 
{
	for(int i=1;i<=n;i++)
	{
		father[i]=i;
		isRoot[i]=false; 
	}	
}

int main()
{
	int n,m,a,b;
	scanf("%d%d",&n,&m);
	init(n);
	for(int i=0;i<m;i++)
	{
		scanf("%d%d",&a,&b);
		Union(a,b);  //边读入,边合并! 
	}
	for(int i=1;i<=m;i++)
	{
		isRoot[findFather(i)]=true;  //多次重写没事!写起来简单! 
	}
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		ans+=isRoot[i];
	}
	printf("%d\n",ans);
	return 0;
}
发布了180 篇原创文章 · 获赞 64 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/OpenStack_/article/details/104064598