HDU 1272 小希的迷宫

题目:

Problem Description

上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让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

思路:

  • 先初始化成独立节点,随后判断两个结点是否有相同的根节点,若相同则构成回路,不符合题意要输出No;若不相同则将其合并成一个连通图。
  • 外加一个标记访问的数组,记录访问过的结点。访问过该节点则说明该节点已是连通图的一部分。

代码:

 1 #include<iostream>
 2 #define MAXN 100005
 3 using namespace std;
 4 
 5 int pre[MAXN];  //前驱数组
 6 int mark[MAXN];  //标记数组
 7 int flag = 1;  //标记是否为回路
 8 
 9 void init()  //初始化成独立节点
10 {
11     for(int i = 0; i < MAXN; i++)
12     {
13         pre[i] = i;
14         mark[i] = 0;
15     }
16        
17 }
18 
19 int find(int x)  //寻找当前节点的根节点
20 {
21     while(x != pre[x])
22         x = pre[x];
23     
24     return x;
25 }
26 
27 void merge(int x, int y)  //判断两个结点的根节点是否相同
28 {
29     int fx, fy;
30     fx = find(x);
31     fy = find(y);
32     if(fx != fy)  //若不相同则合并
33         pre[fx] = fy;
34     else  
35         flag = 0;  //相同则构成回路
36 }
37 
38 int main()
39 {
40     int a, b;
41 
42     while(scanf("%d %d", &a, &b) != EOF)
43     {
44         init();    
45         if(a == 0 && b == 0)
46         {
47             printf("Yes\n");
48             continue;
49         }
50         if(a == -1 && b == -1)
51             break;
52     
53         mark[a] = 1;  //记录访问过的结点
54         mark[b] = 1;    
55         merge(a, b);
56         while(scanf("%d %d", &a, &b) != EOF && a && b)
57         {
58                 mark[a] = 1;
59                 mark[b] = 1;
60                 merge(a, b);            
61         }
62         if(!flag)  //构成回路则不符合
63         {
64             printf("No\n");
65             continue;        
66         }
67         else
68         {
69             int cnt = 0;
70             for(int i = 0; i < MAXN; i++)
71             {
72                 if(mark[i] && pre[i] == i)  //如果访问过当前节点且当前结点为根节点,计数一次
73                     cnt++;
74             }
75             
76             if(cnt == 1)  //cnt == 1,说明连通图只有一个根结点,不构成回路
77                 printf("Yes\n");
78             else      //cnt != 1,说明存在回路
79                 printf("No\n");
80         }        
81         
82     }
83     return 0;
84  } 

 WA代码:

 1 #include<iostream>
 2 #define MAXN 100005
 3 using namespace std;
 4 
 5 int pre[MAXN];
 6 int mark[MAXN] = {0};
 7 int flag = 1;
 8 
 9 void init()
10 {
11     for(int i = 0; i < MAXN; i++)
12     {
13         pre[i] = i;
14     }
15        
16 }
17 
18 int find(int x)
19 {
20     while(x != pre[x])
21         x = pre[x];
22     
23     return x;
24 }
25 
26 void merge(int x, int y)
27 {
28     int fx, fy;
29     fx = find(x);
30     fy = find(y);
31     if(fx != fy)
32         pre[fx] = fy;
33     else
34         flag = 0;
35 }
36 
37 int main()
38 {
39     int a, b;
40 
41     while(scanf("%d %d", &a, &b) != EOF)
42     {
43         init();    
44         if(a == 0 && b == 0)
45         {
46             printf("Yes\n");
47             continue;
48         }
49         if(a == -1 && b == -1)
50             break;
51     
52         mark[a] = 1;
53         mark[b] = 1;    
54         merge(a, b);
55         while(scanf("%d %d", &a, &b) != EOF && a && b)
56         {
57                 mark[a] = 1;
58                 mark[b] = 1;
59                 merge(a, b);            
60         }
61         if(!flag)
62         {
63             printf("No\n");
64             continue;        
65         }
66         else
67         {
68             int cnt = 0;
69             for(int i = 0; i < MAXN; i++)
70             {
71                 if(mark[i] && pre[i] == i)
72                     cnt++;
73             }
74             
75             if(cnt == 1)
76                 printf("Yes\n");
77             else
78                 printf("No\n");
79         }        
80         
81     }
82     return 0;
83  } 

总结:

这题前后一共花了两个多小时,都快三小时了,一直WA,后来把数组初始化的方式改了才AC,实属绝望。
OJ上是不支持这样初始化数组的:

1 int mark[MAXN] = {0};

 也就是说这样不能对数组进行有效的初始化,虽然在自己编译器上是可以的,但是OJ上不行就是不行,这是规则,不遵守规则就要一直WA,直到你想AC为止!

posted @ 2019-07-06 13:20  Anzer  阅读(111)  评论(0编辑  收藏  举报