题目链接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;
}