[并查集] 通信系统
题目描述
某市计划建设一个通信系统。按照规划,这个系统包含若干端点,这些端点由通信线缆链接。消息可以在任何一个端点产生,并且只能通过线缆传送。每个端点接收消息后会将消息传送到与其相连的端点,除了那个消息发送过来的端点。如果某个端点是产生消息的端点,那么消息将被传送到与其相连的每一个端点。为了提高传送效率和节约资源,要求当消息在某个端点生成后,其余各个端点均能接收到消息,并且每个端点均不会重复收到消息。现给你通信系统的描述,你能判断此系统是否符合以上要求吗?
输入
输入包含多组测试数据。每两组输入数据之间由空行分隔。
每组输入首先包含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时,输入结束。
每组输入首先包含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时,输入结束。
输出
对于每组输入,如果所给的系统描述符合题目要求,则输出Yes,否则输出No。
样例输入
4 3
1 2
2 3
3 4
3 1
2 3
0 0
样例输出
Yes
No
分析:题目大致意思等同于,给定几个点和几条边,问从某点开始能否遍历所有点,并且这个图中没有环。该题可以使用并查集来做。在进行合并时,合并的集合cnt++,表示当前合并的集合总数。另外要注意判断是否有环的问题,当进行合并的时候,如果两个节点拥有相同的祖先,则再加一条边就会形成环。
#include <iostream> using namespace std; int f[1010]; int cnt=0; int findFather(int x) { int a=x; while(x!=f[x]) { x=f[x]; } while(a!=f[a]) { int z=a; a=f[a]; f[z]=x; } return x; } int flag_false=0; bool unionf(int a,int b) { int fa=findFather(a); int fb=findFather(b); if(fa!=fb) { cnt++; f[fa]=fb; return true; } else { flag_false=1; return false; } } int main() { int m,n; while(cin>>n>>m) { if(m==0&&n==0) break; for(int i=1;i<1010;i++) { f[i]=i; } int a,b; cnt=1; flag_false=0; for(int i=0;i<m;i++) { cin>>a>>b; unionf(a,b); } if(cnt==n&&flag_false==0) { cout<<"Yes"<<endl; } else { cout<<"No"<<endl; } } }
——来自 熊猫 [http://www.cnblogs.com/xiongmao-cpp/]