机试算法讲解: 第33题 并查集之找小伙伴

/*
问题:1000 0000个朋友,之中有n对朋友,朋友关系具有传递性。要求找出一个最大(人数最多)的集合,该集合中任意两人都是朋友或者只有1个人,输出最大人数
本质:比较每个并查集中元素个数,可以在根结点处设置一个数组用来保存每个根结点对应元素个数,在合并时累加被合并集合中的元素个数
输入:
4
1 2
3 4
5 6
1 6

4
1 2
3 4
5 6
7 8
输出:
4
2
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 10000001
int Tree[N];
int Num[N];//Num[i]表示以节点i为根结点的总节点个数,其中保存Tree[i]为-1,为该节点为树的根结点时有效
int findRoot(int x)
{
	//如果父节点是-1,表明当前节点为根结点
	if(-1==Tree[x])
	{
		return x;
	}
	else
	{
		//寻找父节点的根结点
		int iRoot = findRoot(Tree[x]);
		//设置当前节点的父节点为根结点
		Tree[x] = iRoot;
		//返回根节点
		return iRoot;
	}
}

int main(int argc,char* argv[])
{
	int n,i;
	while(EOF!=scanf("%d",&n))
	{
		//初始化节点信息
		for(i = 1 ; i < N ; i++)
		{
			Tree[i] = -1;
			//同时要加入根结点的树的总节点个数
			Num[i] = 1;
		}

		//获取输入的n对数据信息
		int a,b;
		for(i = 0 ; i < n;i++)
		{
			scanf("%d %d",&a,&b);
			int iRoot1 = findRoot(a);
			int iRoot2 = findRoot(b);
			if(a!=b)
			{
				Tree[a] = b;
				//这里不能用2,因为后面Sum[a]可能不是2
				//Sum[b] = 2;
				//Num[b] += Num[a];//这里应该用查找到的根结点的值进行累加,而不是用子节点的值进行累加
				Num[iRoot2] += Num[iRoot1];
			}
		}
		//统计答案,至少为1
		int iResult = 1;
		//for(i = 0 ; i < N ; i++)
		for(i = 1; i < N;i++)
		{
			if(Tree[i]==-1 && Num[i] > iResult)
			{
				iResult = Num[i];
			}
		}
		printf("%d\n",iResult);
	}
	system("pause");
	getchar();
	return 0;
}

你可能感兴趣的:(并查集,机试算法)