上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一个通道连通了房间A和B,那么既可以通过它从房间A走到房间B,也可以通过它从房间B走到房间A,为了提高难度,小希希望任意两个房间有且仅有一条路径可以相通(除非走了回头路)。小希现在把她的设计图给你,让你帮忙判断她的设计图是否符合她的设计思路。比如下面的例子,前两个是符合条件的,但是最后一个却有两种方法从5到达8。
大意就是说无向图中没有环且图连通,当然不能用拓扑排序的方法了,因为10000的数据量且边的多少也没法确定,判断方法就是并查集,如果a-b且b-c那么现在a-c相连就会构成回路.放入并查集的模型如下:
t1=find(b);
t2=find(c);
if (t1!=t2)
pre[t2]=t1;
else
flag=0;//否则a-b相连,b-c相连,然后a-b又相连,形成环.
哪怕是特殊数据比如1-2,2-1那也构成了环,一开始没想清楚.
最后判断连通就没必要在BFS了,因为连通必然会导致所有点的根节点都是同一个点,先取find(第一个被访问的点)再看看和后面find(被访问的点)是否相等,当然需要一个vis记录下被访问的点.
给几个测试用例:
0 0 yes 1 1 0 0 yes 1 2 2 1 0 0 no
#include <stdio.h>
#include <string.h>
int pre[100005];
int vis[100005];
int n,m,flag;
int find(int i)
{
int j=i,temp;
while (pre[i]!=i)
i=pre[i];
while (j!=i)
{
temp=pre[j];//先记录下下一个长官
pre[j]=i;//统一都更新为i的手下
j=temp;//迭代
}
return i;
}
void merge(int b,int c)
{
int t1,t2;
if (b==c)
return;
t1=find(b);
t2=find(c);
if (t1!=t2)
pre[t2]=t1;
else
flag=0;//否则a-b相连,b-c相连,然后a-b又相连,形成环.
return;
}
int main()
{
int i,j,a,b,k,t;
while(scanf("%d%d",&a,&b)==2&&(a!=-1||b!=-1))
{
flag=1;
memset(vis,0,sizeof(vis));
for (i=1;i<=100005;i++)
pre[i]=i;
merge(a,b);
vis[a]=1;
vis[b]=1;
if ((a==0)&&(b==0))
{
printf("Yes\n");
continue;
}
while(scanf("%d%d",&a,&b)==2&&(a!=0||b!=0))
{
merge(a,b);
vis[a]=1;
vis[b]=1;
}
j=1;
while(vis[j]==0)
j++;
k=find(j);
for (i=j+1;i<=100000;i++)
if ((vis[i])&&(find(i)!=k))
{
flag=0;
break;
}
if (flag)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}