这道题,最开始我想用最小生成树(无向)来解决的,然后发现好像写不出来。
看了博客后发现,这道题用并查集来做。
需要涉及到俩个问题:
一、判断成环的时候,只要判断输入边的两个点。有一个共同的父节点,那么这两个点就成环。
二、判断连通的时候,只要判断根节点数为1。或者说:顶点个数+1 = 边的条数
所以我们用了一个edgenum存边的条数,vnum来存顶点数
#include<stdio.h>
#include<iostream>
using namespace std;
bool circle; //判断是否有环
const int Max = 100002;
int par[Max];
bool visit[Max];//在Max个点中,判断是否访问过这个点,由此记录一共有多少个顶点
int edgenum,vnum;
void init()
{
for(int i=1;i<Max;i++)
{
par[i]=i,visit[i]=false;
}
circle = false;
edgenum = vnum = 0;
}
int find (int x)
{
if(par[x]==x)
{
return x;
}
else{
return par[x]=find(par[x]);
}
}
void unite (int x,int y)
{
if(x==y) circle = true;
x=find(x);
y=find(y);
if(x!=y) {
par[x]=y;
edgenum++;
}else circle = true;
}
int main()
{
int a ,b;
while(true)
{
init();
scanf("%d%d",&a,&b);
if(a==0&&b==0){
printf("Yes
");
continue;
}
if(a==-1&&b==-1) break;
visit[a] = true;
visit[b] = true;
unite(a ,b);
while(true){
scanf("%d%d",&a,&b);
if(a==0 && b==0) break;
visit[a] = true;
visit[b]= true;
unite(a,b);
}
for(int i=1;i<Max; i++)
if(visit[i]) vnum++;
if(!circle && edgenum+1 == vnum)
printf("Yes
");
else
printf("No
");
}
return 0;
}