广播系统

题目描述

为了更加快速的传递学习任务,ACM集训队计划建设一个广播系统!按照规划,这个系统包含若干端点,这些端点由神奇的网络连接。
此网络有下述特点:
1.消息可以在任何一个端点产生,并且只能通过这个网络传递信息。每个端点接收消息后会将消息传送到与其相连的端点(单项传输,不会传输到那个消息发送过来的端点)
2.如果某个端点是产生消息的端点,那么消息将被传送到与其相连的每一个端点。
3.当消息在某个端点生成后,其余各个端点均能接收到消息
4.任意一个消息可以被快速的传给所有端点
现给你这个广播系统的连接方案,你能判断此系统是否符合以上要求并且传递给所有的端点?

Input

输入包含多组测试数据。每两组输入数据之间由空行分隔。
每组输入首先包含2个整数N和M,N(1<=N<=1000)表示端点个数,M(0<=M<=N*(N-1)/2)表示通信线路个数。
接下来M行每行输入2个整数A和B(1<=A,B<=N),表示端点A和B由神奇的网络相连。两个端点之间至多由一条网络直接相连,并且没有将某个端点与其自己相连的网络。
当N和M都为0时,输入结束。

Output

对于每组输入,如果所给的系统描述符合题目要求,则输出Yes,否则输出No。

sample Input

4 3
1 2
2 3
3 4

3 1
2 3

0 0

sample Output

Yes
No

心路历程

在ACM集训队的月考核中见到了这一题,一开始题目看上去好像很复杂,读完后发现好像就是一个并查集,很简单的样子 ,就很自信的开始写了,并且还在疑惑为什么题目里要给出那么多的特点。最后改了好几遍都只能过一半的样例,无奈放弃。考核完后和朋友(大佬)讨论,才发现看漏了重要条件。

解题思路

这题就是很基础的并查集,相信会并查集的各位都能很容易的写出来。根据题目中的特点1,我们发现这个网络是单向传输的,也就是如果是甲发的消息,那么甲就不能接受到这条消息。换句话说,这个系统不能有环状结构存在。所以我们不光需要判断根节点是不是只有一个,还需要判断是不是有环。受到大佬(博客名:CTGU-liyb)的点拨,发现判断是不是环,只需要判断端点的数目是不是等于线路的数目加一即可

#include <iostream>
#include <algorithm>

using namespace std;
const int N = 1e3 + 5;
int fa[N], n, m;

//初始化 fa 数组,让每个元素的根节点是自己
void init()
{
	for (int i = 1; i <= n; i++)
		fa[i] = i;
}

//找到一个元素的根节点
int find(int x)
{
	if (x == fa[x])	return x;
	else return		fa[x] = find(fa[x]);//路径压缩,方便后续查找
}

//判断所有元素是不是在同一集合
bool check()
{
	int root = find(1);
	for (int i = 1; i <= n; i++)
	{
		if (find(i) != root)
			return false;
	}
	return true;
}

int main()
{
	int a, b;
	while (cin >> n >> m)
	{
		if (n == 0 && m == 0)
			break;
		init();
		for (int i = 0; i < m; i++)
		{
			cin >> a >> b;
			fa[find(a)] = find(b);//将有关联的元素放在一个集合
		}
		if (check() && m == n - 1)//判断是否存在环状结构
			cout << "Yes" << endl;
		else
			cout << "No" << endl;
	}
	return 0;
}
  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值