hdu--1272--并查集||图的特点

其实 觉得 这个标题 起得不太恰当...

但我又想 并查集 的操作 是形成一颗树的结构 这题的话 是基于图来考虑比较好

因为 是中文 很容易理解题意 而且我一般也不喜欢讲题意 就想随便讲下应该注意和考虑的地方 从我的角度来出发

这题 一开始我的考虑方向是 给出的这些点会不会形成回路 就是成环 如果出现了 那就肯定是NO的

因为 题目要求 任意两点之间 路径的 唯一性 如果 成环 那就会有多条路径的出现了

至于这个是否会成环的判断 不难想到 对于每次输入的x y 通过find操作得到他们各自的 根结点  然后比较 根结点 是否相同即可

但 单纯这样操作 还不够  这样只是保证了 不会出现 成环的存在 但不能保证 只存在一个连通分量----也就是 你可以看这组数据 1 2      3  4     0  0

那么 其实是2个连通分量 虽然是不存在环的

那么怎么判断连通分量是否只有一个呢?  我们可以通过 father[x] == x来进行判断 如果是1 就是Yes的了

******************这是 一种方法

另外 还有一种 更巧妙的方法是    

根据图的定义:在无向图中 如果一个图 既不含 平行边 与不含 环 那么称为 简单图  --- 其实 这题 在我看来 就是求是否给出的这些点 能构成一张 简单图

<但我的这概括并不严谨  如果 题目数据出现了平行边 那么按照我的判断方法是错误的 但是 这题的数据中是没有平行边的>

边的数目+1 == 顶点的数目

OK 接下来 直接上3份代码....

对于 第二种方法 我进行了使用 set与 vis数组的测试  结果 使用set的方法在时间上 和 内存上都消耗更大 但是代码 简洁

 1 #include <iostream>
 2 #include <set>
 3 using namespace std;
 4 
 5 set<int>s;
 6 
 7 int main()
 8 {
 9     int x, y, side;
10     while (cin >> x >> y)
11     {
12         s.clear();
13         side = 0;
14         if (x == -1 && y == -1)
15             break;
16         if (x == 0 && y == 0)
17         {
18             cout << "Yes" << endl;
19         }
20         else
21         {
22             s.insert(x);
23             s.insert(y);
24             side++;
25             while (1)
26             {
27                 cin >> x >> y;
28                 if (!x && !y)
29                 {
30                     break;
31                 }
32                 s.insert(x);
33                 s.insert(y);
34                 side++;
35             }
36             if (s.size() == side + 1)
37                 cout << "Yes" << endl;
38             else
39                 cout << "No" << endl;
40         }
41     }
42     return 0;
43 }
View Code
 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int size = 100010;
 7 bool vis[size];
 8 
 9 int main()
10 {
11     int x , y , side , point , mmax;
12     while( cin >> x >> y )
13     {
14         memset( vis , false , sizeof(vis) );
15         mmax = side = point = 0;
16         if( x==-1 && y==-1 )
17             break;
18         if( x==0 && y==0 )
19         {
20             cout << "Yes" << endl;
21         }
22         else
23         {
24             vis[x] = true;
25             vis[y] = true;
26             side ++;
27             mmax = max( mmax , max(x,y) );
28             while(1)
29             {
30                 cin >> x >> y;
31                 if( !x && !y )
32                 {
33                     break;
34                 }
35                 vis[x] = true;
36                 vis[y] = true;
37                 side ++;
38                 mmax = max( mmax , max(x,y) );
39             }
40             for( int i = 1 ; i<=mmax ; i++ )
41             {
42                 if( vis[i] )
43                     point ++;
44             }
45             if( point == side+1 )
46                 cout << "Yes" << endl;
47             else
48                 cout << "No" << endl;
49         }
50     }
51     return 0;
52 }
View Code
  1 //Runtime Error Stack OverFlow
  2 //#include "stdafx.h"
  3 #include <iostream>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 bool flag;
  8 int mmax;
  9 const int size = 100010;
 10 int father[size];
 11 bool vis[size];
 12 
 13 void init()
 14 {
 15     for (int i = 0; i <= size - 5; i++)
 16     {
 17         father[i] = i;
 18         vis[i] = false;
 19     }
 20 }
 21 
 22 int find(int x)
 23 {
 24     while( x != father[x] )
 25     {
 26         father[x] = father[ father[x] ];
 27         x = father[x];
 28     }
 29     return x;
 30 }
 31 
 32 /*
 33 int find(int x)
 34 {
 35     return x == father[x] ? x : father[x] = find(father[x]);
 36 }
 37 */
 38 
 39 void Union(int x, int y)
 40 {
 41     vis[x] = true;
 42     vis[y] = true;
 43     x = find(x);
 44     y = find(y);
 45     if (x != y)
 46     {
 47         //father[y] = x;
 48         father[x] = y;
 49     }
 50     else
 51     {
 52         flag = false;
 53     }
 54 }
 55 
 56 void getMax(int x, int y)
 57 {
 58     mmax = max(mmax, max(x, y));
 59 }
 60 
 61 int main()
 62 {
 63     int t = 0;
 64     int x, y, cnt;
 65     while (cin >> x >> y)
 66     {
 67         init();
 68         flag = true;
 69         cnt = mmax = 0;
 70         if (x == -1 && y == -1)
 71             break;
 72         if (x == 0 && y == 0)
 73         {
 74             cout << "Yes" << endl;
 75         }
 76         else
 77         {
 78             getMax(x, y);
 79             Union(x, y);
 80             while (1)
 81             {
 82                 cin >> x >> y;
 83                 if (!x && !y)
 84                     break;
 85                 getMax(x, y);
 86                 Union(x, y);
 87             }
 88             if (!flag)
 89             {
 90                 cout << "No" << endl;
 91             }
 92             else
 93             {
 94                 for (int i = 1; i <= mmax; i++)
 95                 {
 96                     if (vis[i] && father[i] == i)
 97                     {
 98                         cnt++;
 99                     }
100                 }
101                 if (cnt == 1)
102                     cout << "Yes" << endl;
103                 else
104                     cout << "No" << endl;
105             }
106         }
107         //if (t++)
108         //  cout << endl;
109     }
110     return 0;
111 }
View Code

这里 题目 有一点很坑的地方... 

你按照它要求 去输出空行 反而是PE 

单纯输出一行 就AC了

卧槽了。。。。  还好去看了discuss  真TM无语

这里的代码格式 与我之前都有一些不同 因为我这台机子 sublime编译环境搭建不好 =-=  我只能在sublime上写 最近cfree编译有点迟钝..我就昨天下了个vs2013 然后今天是在vs上面进行编译的 但vs吧 会自动更正我的代码格式 厌死了。。。 可能 可以自己设置 让它不更正吧 我也不知道 没去找过

PS:打完一把 如此惊心动魄的游戏 之后 才想起来了 有1点忘记说了

这题 我刚开始用递归版本的find的时候出现了 stack overflow 可能是递归层次太多了吧  但TM看到了discuss里说 将它改成 father[y] = x就可以了 我试了下 的确...

这应该是和 数据有关系吧

然后 我的做法是 就采用了非递归版本的查找 就是通过while来实现  也是很容易写的

just follow your heart
原文地址:https://www.cnblogs.com/radical/p/3908387.html