[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结尾。
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 }
View Code
posted @ 2015-06-03 14:39  TonyFang  阅读(169)  评论(0编辑  收藏  举报