[并查集] 通信系统

题目描述

某市计划建设一个通信系统。按照规划,这个系统包含若干端点,这些端点由通信线缆链接。消息可以在任何一个端点产生,并且只能通过线缆传送。每个端点接收消息后会将消息传送到与其相连的端点,除了那个消息发送过来的端点。如果某个端点是产生消息的端点,那么消息将被传送到与其相连的每一个端点。为了提高传送效率和节约资源,要求当消息在某个端点生成后,其余各个端点均能接收到消息,并且每个端点均不会重复收到消息。现给你通信系统的描述,你能判断此系统是否符合以上要求吗?

输入

输入包含多组测试数据。每两组输入数据之间由空行分隔。
每组输入首先包含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;
        }
    }
}

 

posted @ 2017-02-23 14:38  Num.Zero  阅读(631)  评论(0编辑  收藏  举报