[HDU 1272] 小希的迷宫
小希的迷宫
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/32768 K (Java/Others)
Problem Description
上次Gardon的迷宫城堡小希玩了很久,现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一个通道连通了房间A和B,那么既可以通过它从房间A走到房间B,也可以通过它从房间B走到房间A,为了提高难度,小希希望任意两个房间有且仅有一条路径可以相通(除非走了回头路)。小希现在把她的设计图给你,让你帮忙判断她的设计图是否符合她的设计思路。比如下面的例子,前两个是符合条件的,但是最后一个却有两种方法从5到达8。
Input
输入包含多组数据,每组数据是一个以0 0结尾的整数对列表,表示了一条通道连接的两个房间的编号。房间的编号至少为1,且不超过100000。每两组数据之间有一个空行。
整个文件以两个-1结尾。
整个文件以两个-1结尾。
Output
对于输入的每一组数据,输出仅包括一行。如果该迷宫符合小希的思路,那么输出"Yes",否则输出"No"。
Sample Input
6 8
5 3
5 2
6 4
5 6
0 0
8 1
7 3
6 2
8 9
7 5
7 4
7 8
7 6
0 0
3 8
6 8
6 4
5 3
5 6
5 2
0 0
-1 -1
Sample Output
Yes
Yes
No
【题解】
其实这道题就是运用并查集来判断是否存在环且是否全图为连通图。
判断是否存在环就是在join的时候判断如果已经join过了,那么就有环了,输出false。
判断全图为连通图就是找根节点,如果只有一个,那么就是联通的。
代码实现如下:
时间复杂度 O(Tk) (T为数据组数,k为有多少条边)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int pre[100001],r[100001]; 4 bool vis[100001]; 5 bool flag=0; 6 int findset(int x) { 7 int r=x; 8 while(pre[r]!=r) r=pre[r]; 9 int i=x,j; 10 while(i!=r) { 11 j=pre[i]; 12 pre[i]=r; 13 i=j; 14 } 15 return r; 16 } 17 void join(int f1,int f2) { 18 if(r[f1]<=r[f2]) { 19 pre[f1]=f2; 20 if (r[f1]==r[f2]) r[f2]++; 21 } 22 else pre[f2]=f1; 23 } 24 int main() { 25 int a,b; 26 while(~scanf("%d%d",&a,&b)) { 27 for (int i=1;i<=100000;++i) pre[i]=i,r[i]=1; 28 memset(vis,0,sizeof(vis)); 29 if (a==-1&&b==-1) break; 30 if (a==0&&b==0) { 31 printf("Yes\n"); 32 continue; 33 } 34 int sign=0,minn=1000001,maxn=-1; 35 do { 36 minn=min(min(minn,a),b); 37 maxn=max(max(maxn,a),b); 38 vis[a]=vis[b]=1; 39 int f1=findset(a),f2=findset(b); 40 if(f1==f2) sign=-1; 41 else join(f1,f2); 42 scanf("%d%d",&a,&b); 43 if(a==0&&b==0) break; 44 }while(1); 45 if(sign==-1) { 46 printf("No\n"); 47 continue; 48 } 49 bool x=0; 50 for (; minn<=maxn; minn++) 51 if(vis[minn] && pre[minn]==minn) { 52 if(x==1) {x=0;break;} 53 else x=1; 54 } 55 if(x) printf("Yes\n"); 56 else printf("No\n"); 57 } 58 return 0; 59 }
这篇文章由TonyFang发布。
所有解释权归TonyFang所有。
Mailto: tony-fang@map-le.net