Java教程

How Many Tables 普通并查集

本文主要是介绍How Many Tables 普通并查集,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

天是伊格那丢的生日。他邀请了很多朋友。现在该吃晚饭了。伊格那丢想知道他至少需要多少张桌子。你要注意,并不是所有的朋友都认识彼此,所有的朋友都不想和陌
生人呆在一起。
这个问题的一个重要规则是如果我告诉你A认识B, B认识C,这意味着A B C彼此认识,所以它们可以留在一个表中。
例如,如果我告诉你A知道B, B知道C, D知道E,那么A, B, C可以留在一个表中,而D, E必须留在另一个表中。所以伊格那丢至少需要两张桌子。

输入以整数T(1<=T<=25)开始,表示测试用例的数量。
然后是T测试用例。
每个测试用例都以两个整数N和M开始(1<=N,M<=1000)。
N表示朋友的数量,从1到N,后面有M行。
每一行由两个整数A和B组成(A!=B),表示朋友A和朋友B认识。
两种情况之间将有一条空行。

对于每个测试用例,只输出Ignatius至少需要多少个桌子。不要打印任何空白。
input
2
5 3
1 2
2 3
4 5
father[1~5]:1->2 2->3 3->3 4->5 5->5根节点只有2个 
5 1
2 5
output
2
4

错误思路
开个father[N],默认为0,再写个初始化函数,每个案例先变0,再初始化成i,路径压缩,最后在1~n查询有多少个不同的根节点 
错因:    没有理解合并并查集的操作  

正确思路:合并并查集后再查询

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=1001;
int father[N];
void inf(int n)//初始化 
{
	for(int i=1;i<=N;i++)	father[i]=i;
}
bool judge(int x)//判断是否为根节点 
{
	if(x==father[x]) return true;
	else return false;
}
int findFather(int x)
{
	//由于x在下面的while中会变成根结点, 因此先把原先的x保存一下
	int temp=x;
	while(x!=father[x]){//寻找根节点 
		x=father[x];
	}
	//到这里, x存放的是根结点。 下面把路径上的所有结点的father都改成根结点
	while(temp!=father[temp])
	{
		int t=temp;//因为temp要被father[temp]覆盖, 所以先保存temp的值, 以修改father[temp]
		temp=father[temp];
		father[t]=x;//将原先的结点temp的父亲改为根结点x
	}
	return x; //返回根结点
}
void Union (int a,int b)//U务必大写,因为union是个关键字 
{
	int faA=findFather(a);
	int faB=findFather(b);
	if(faA==faB)	return;//判断它们是否属于同一集合
	else{
		father[faB]=faA;//把其中一个的父亲结点指向另一个结点
	}
}
int cnt(int n)
{
	int ans=0;
	for(int i=1;i<=n;i++)
		if(judge(i))	ans++;
	return ans;
}
int main(){
	int T;cin>>T;
	while(T--)
	{
		memset(father,0,sizeof(father));
		int n,m;
		cin>>n>>m;
		inf(n);
		while(m--)
		{
			int a,b;
			cin>>a>>b;
			Union(a,b);
		}
		cout<<cnt(n)<<endl;	
	}
	return 0;
} 

这篇关于How Many Tables 普通并查集的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!