并查集。题目要求的迷宫有两个特点:1:无环、2:单根,因此,若同一边上的两个点拥有相同的父节点,则可以认为有环,最后加一个扫描,判断根节点个数。
若一条边的两个节点为同一个父节点,则成环。若所有的节点的父节点相同则联通。注意输入0 0时为Yes。
拓展:改为有向图hdu1325
1:保证图是连通的,且连通分量为1( 即从一点可以到任意一点 )
2:不存在环(包括自环)
因为这是一个无向图,只要保证 顶点数 = 边数+1 , 就可以说明是连通的。如果存在1->2 , 2->3 , 1->3这样的图话,虽然满足了左面的公式,但是已经成了环,所以也不会影响到最后的判断。
#include<bits/stdc++.h> using namespace std; const int M= 100005; int a,b; int father[M]; //记录父节点 bool circle; //判断是否存在环 bool visit[M]; //用来记录顶点数 int edgenum,pointnum; //分别表示边数,顶点数 void init( ) { for( int i=0 ; i<M ; i++ ) father[i] = i,visit[i]=false; circle = false; edgenum = pointnum = 0; } int Find( int x ) { return x==father[x]?x:father[x]=Find(father[x]); } void unin( int a,int b ) { if(a==b) circle = true; int x, y; x = Find(a); y = Find(b); if( x != y ) { father[x] = y; edgenum++; //引出一条边 } else circle = true; //x==y,说明他们是同一个祖先,一旦连通便与祖先3者成环 } int main() { while( true ) { init( ); scanf("%d%d",&a,&b); if( a==0 && b==0 ) //为空树 { printf("Yes\n"); continue; } if( a==-1 && b==-1 ) break; visit[a] = true; visit[b] = true; unin( a,b ); while( true ) { scanf("%d%d",&a,&b); if( a==0 && b==0 ) break; visit[a] = true; visit[b] = true; unin( a, b ); } for( int i=0 ; i<M ; i++ ) if( visit[i] ) pointnum++; if( !circle && edgenum+1 == pointnum ) printf("Yes\n"); else printf("No\n"); } return 0; }
#include<bits/stdc++.h> using namespace std; const int N=100000+5; bool circle;//判断是否形成个环 int fa[N]; int Find(int x)//爆栈就是在这里 { if(fa[x]!=x) fa[x]=Find(fa[x]); return fa[x]; } void uni(int x,int y) { int xx=Find(x); int yy=Find(y); if(xx!=yy) fa[xx]=yy; else circle=true; //第一次合并绝对不会出现环 //只有游乐环才会第二次合并。 } void init() { for(int i=1; i<N; i++) fa[i]=i; } int main() { set<int>s;//至于这个set容器可以用来找顶点,在这个容器里重复的数字只计一次 int a,b,sum;//sum计算边 while(scanf("%d %d",&a,&b)!=EOF) { init(); sum=1,circle=false; if(a==0&&b==0)//这也是一个比较坑的地方 { printf("Yes\n"); continue; } if(a==-1&&b==-1) break; s.insert(a); s.insert(b); if(!circle) uni(a,b); while(1) { scanf("%d %d",&a,&b); if(a==0&&b==0) break; s.insert(a),s.insert(b); if(!circle) uni(a,b); sum++; } if(!circle&&s.size()==sum+1) printf("Yes\n"); else printf("No\n"); s.clear(); } return 0; }