上次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; }