题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1272

解题思路:


并查集

输出Yes的情况有:

1).该组数据中只有0 0

2).图中任意两个结点之间只有一条通路

输出No的情况有:

1).图不连通,并查集中有多个父结点

2).待合并的两个顶点n,m经过查找发现它们两个的父结点相同,即已经在同一个集合中

注意:

1.有些数字不会在一组数据中出现,用visit数组标记出现过的数字

2.在判断某个结点是否是父结点是用if(visit[i]&&father[i]=i)判断即可,无需再调用查找父结点的函数,否则容易超时

ac代码:


#include <iostream>
#include <vector>
#include <string.h>
#include <cmath>
#include <algorithm>
#define maxn 100001
using namespace std;
int father[maxn];
int visit[maxn];
int findfather(int x)
{
    while(x!=father[x])
        x=father[x];
    return x;
}
bool Union(int n,int m)
{
    int N=findfather(n);
    int M=findfather(m);
    if(N==M)
        return false;
    else
    {
        father[N]=M;
        return true;
    }
}
int main()
{
    int n,m,i;
    while(scanf("%d %d",&n,&m))
    {
        bool flag=true;
        int num=0;
        if(m==-1&&n==-1)
            break;
        if(n==0&&m==0)
        {
            printf("Yes\n");
            continue;
        }
        for(i=1;i<maxn;i++)
        {
            father[i]=i;
            visit[i]=0;//是否出现
        }
        visit[n]=visit[m]=1;
        bool ans=Union(n,m);
        if(!ans) flag=false;
        while(scanf("%d %d",&n,&m)&&n!=0&&m!=0)
        {
            visit[n]=visit[m]=1;
            if(!Union(n,m))
                flag=false;
        }
        for(i=1;i<maxn;i++)
        {
            if(visit[i]&&father[i]==i)
                num++;//判断是否是连通图
        }
        printf("%s\n",flag&&(num==1)?"Yes":"No");

    }
    return 0;
}