题目大意:
不断连接两个点,问最后是否是一个无向连通图,且每两个点只有一条通路。
思路:
这题用并查集,但是有几个注意的地方值得记住:
1、要判断是否只有一个连通图,即判断有几个集合,par[i]==i的为一个集合,i是要出现过的
同时你会发现,par[]里面存的是当前节点的父节点,并不都是根节点,因为后加入的节点,
其父节点没有得到更新,是当前加入的节点。这里用set存储出现过的点。迭代用set<int>::iterator i;
#include <iostream>
#include<set>
using namespace std;
#define maxn 100008
int ranks[maxn];
int par[maxn];
bool save[maxn];
void init(int n)
{
for(int i=1;i<=n;i++)
{
ranks[i]=0;
par[i]=i;
save[i]=0;
}
}
int finds(int x)
{
int t=x;
while(t!=par[t])
t=par[t];//压缩路径
par[x]=t;
return t;
}
void unions(int x,int y)
{
int rootx=finds(x);
int rooty=finds(y);
if(rootx!=rooty)
{
if(ranks[rootx]<ranks[rooty])
par[rootx]=rooty;
else
{
par[rooty]=rootx;
if(ranks[rootx]==ranks[rooty])
ranks[rootx]++;
}
}
}
int main()
{
while(1)
{
init(100000);
int xx,yy;
bool f=0;
int num=0;
set<int> Q;
while(cin>>xx>>yy&&xx+yy!=0)
{
num++;
if(xx==-1&&yy==-1)
{
return 0;
}
if(f==1)
continue;
Q.insert(xx);
Q.insert(yy);
int fx=finds(xx);
int fy=finds(yy);
if(fx==fy)
{
f=1;
cout<<"No"<<endl;
}
unions(xx,yy);
}
if(f==0)
{//判断所有房间是否连通
int cur;int sum=0;
set<int>::iterator i;
for(i=Q.begin();i!=Q.end();i++)
{
cur=*i;
//cout<<cur<<" "<<finds(cur)<<endl;注意此时4的根节点还是6,没有更新,因为6是后面才加入到大集合中
if(par[cur]==cur)
sum++;
}
if(sum>1)
cout<<"No"<<endl;
else
cout<<"Yes"<<endl;
// cout<<"xx"<<xx<<"yy"<<yy<<endl;
}
}
return 0;
}