并查集算法(杭电1213题)

并查集算法水题(杭电1213)

杭电1213题是一道并查集水题题目链接
并查集算法最重要的是三个部分:查找根结点、路径压缩、合并两个结点。查找根结点的算法和路径压缩的算法差不多。
根结点就是person[a]=a的结点,因为根结点不需要认识别人,都是别人认识他。
这道题虽然使用的路径压缩但没有压缩完全(比如1 2,2 3。程序跑出的结果1的根结点是2),若要输出最后的每个的点的根结点,则需要for循环跑一边find函数。不过这道题完全不需要这么做,只需要输出根结点的数量就是答案了~~,因为我们只关心根结点的数量。

#include<iostream>
#include<cstring>
using namespace std;
int n;
int person[1005];
void init()   //并查集数组初始化 
{
	for(int i=0;i<=n;i++)
	   person[i]=i;  //初始化,假设所有人都不认识别人,只认识自己 
}
int find(int a)  //寻找根结点 
{
	int temp=a,root;
	while(a!=person[a])  //寻找根结点 
		a=person[a];
	root=a;  //找到之后,记录根结点 
	a=temp;  //找回初始的叶节点 
	while(a!=person[a])  //并查集的路径压缩 
	{
		temp=person[a];
		person[a]=root;
		a=temp;
	}
	return root;  //返回根结点 
}
void merge(int a,int b)  //合并 
{
	int root;
	while(a!=person[a])  // 寻找a的根结点 
	{
		root=person[a];
		person[a]=b;
		a=root;
	}
	person[a]=b;  //将a的根节点变成b 
}
int main()
{
	int t,a,b,m,fata,fatb,sum;
	cin>>t;  //输入样例数 
	while(t--)
	{
		sum=0;
	    cin>>n>>m;  //输入朋友数、边数 
	    init();  //并查集数组初始化 
		for(int i=0;i<m;i++)
		{
			cin>>a>>b;
			fata=find(a);   fatb=find(b);   //寻找各自的根节点 
			if(fata!=fatb)   merge(a,b);  //若根节点不同,则合并。若相同则不需要干嘛 
		}
	    for(int i=1;i<=n;i++)
	       if(person[i]==i)  sum++;  //记录根的数量 
	    cout<<sum<<endl;  //输出结果 
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39905917/article/details/82956547