hdu1272 小希的迷宫(并查集) 小希的迷宫

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1272

题目

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 63799    Accepted Submission(s): 20016


Problem Description
上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一个通道连通了房间A和B,那么既可以通过它从房间A走到房间B,也可以通过它从房间B走到房间A,为了提高难度,小希希望任意两个房间有且仅有一条路径可以相通(除非走了回头路)。小希现在把她的设计图给你,让你帮忙判断她的设计图是否符合她的设计思路。比如下面的例子,前两个是符合条件的,但是最后一个却有两种方法从5到达8。
hdu1272 小希的迷宫(并查集)
小希的迷宫
 
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
 
Author
Gardon
 
解题思路:并查集入门题,是道水题,但是WA了贼多次。一开始想不用并查集做,但是感觉怎么做都不怎么好做。
 
正确做法当然是用并查集了,当输入的两个数,先判断两个数的根是否相同,相同说明在同一个集合,如果再合并肯定就形成环了。肯定不可以。
如果没有环的话,就只有判断所有的点是否连通,直接判断边的数目是否等于点的数目减一就好了。
 
这题最坑的地方就是开始直接输入0 0是可以的。我在这WA了好多次啊。。。
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<set>
 4 #include<cstring>
 5 using namespace std;
 6 int par[100005],Rank[100005];
 7 set<int> se;   //方便记录点的个数,不会重复 
 8 int flag;
 9 
10 void init(int x)
11 {
12     for(int i=1;i<=x;i++)
13     {
14         par[i]=i;
15         Rank[i]=0;
16     }
17 }
18 
19 int find(int x)
20 {
21     if(par[x]==x)
22         return x;
23     par[x]=find(par[x]);
24     return par[x];
25 }
26 
27 void unite(int x,int y)
28 {
29     int fx=find(x);
30     int fy=find(y);
31     if(fx==fy)
32     {
33         flag=1;  //形成了环,肯定不行 
34         return;
35     }
36     if(Rank[fx]<Rank[fy])
37         par[fx]=fy;
38     else
39     {
40         par[fy]=fx;
41         if(Rank[fx]==Rank[fy]) Rank[fx]++;
42     }
43 }
44 
45 bool same(int x,int y)
46 {
47     return find(x)==find(y);
48 }
49 
50 int main()
51 {
52     int n,m,edge=0; //edge记录边的数目 
53     flag=0;
54     init(100000);
55     while(cin>>n>>m&&(n!=-1||m!=-1))
56     {
57         if(n==0&&m==0)
58         {
59             if(se.size()==0)  //注意 
60             {
61                 cout<<"Yes"<<endl;
62                 continue;
63             }
64             if(edge!=se.size()-1) flag=1;
65             if(flag) cout<<"No"<<endl;
66             else cout<<"Yes"<<endl;
67             flag=0;
68             edge=0;
69             se.clear();
70             init(100000);
71             continue;
72          }
73          edge++;
74         se.insert(n);
75         se.insert(m);
76         unite(n,m);
77     }
78     return 0;
79 }