Codeup.通信系统(并查集)思路与注意点--补充《算法笔记》

通信系统

题目链接

个人思路

本题就是一个并查集的基本操作。

  • 并查集初始化
  • 根据输入数据两两合并
  • 查找根节点并计数,判断所有点均在一个集合内,输出yes,否则为no

有两个值得注意的地方

  • 本题注明要每个节点均要收到消息,并且不能重复收到消息也就是说N个结点都要在一个树型集合内(图则会出现环路),根据树的性质,N个结点连通必须有N-1条边,因此M = N - 1才符合条件(可以把这个判断条件放在最前面,省去多余计算提高运算效率)
  • 由于Codeup是多点测试,要记得每次对全局变量初始化(写PAT没有养成初始化的习惯,找了半天的错误)

Codeup.通信系统(并查集)思路与注意点--补充《算法笔记》_第1张图片

个人思路代码

#include 
using namespace std;
int N, M;
int father[1005];
bool vis[1005];
void init()//初始化 
{
	for(int i = 1; i <= N; ++i)
	{
		father[i] = i;
	}
}
int findFather(int x)
{
	if(x == father[x])
		return x;
	else
	{
		int F = findFather(father[x]);
		father[x] = F;
		return F;
	}
}
void unionFather(int x, int y)
{
	int fx = findFather(x);
	int fy = findFather(y);
	if(fx != fy)
		father[fx] = fy;
}
int main(int argc, char *argv[]) {
	while(1)
	{
		memset(father, 0, sizeof(father));
		memset(vis, false, sizeof(vis));
		scanf("%d%d", &N, &M);
		if(!M && !N)
			break;
		init();
		for(int i = 0; i < M; ++i)
		{
			int a, b;
			scanf("%d%d", &a, &b);
			unionFather(a, b);
		}
		int ans = 0;
		for(int i = 1; i <= N; ++i)
		{
			int F = findFather(i);
			if(!vis[F])
			{
				ans++;
				vis[F] = true;
			}
			if(ans > 1)
			{
				break;
			}
		}
		if(ans == 1 && M == N - 1)
			printf("Yes\n");
		else
			printf("No\n");
	}
	return 0;
}

你可能感兴趣的:(Codeup)