九度oj 题目1012:畅通工程

题目描述:

    某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?

输入:

    测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
    注意:两个城市之间可以有多条道路相通,也就是说
    3 3
    1 2
    1 2
    2 1
    这种输入也是合法的
    当N为0时,输入结束,该用例不被处理。

输出:

    对每个测试用例,在1行里输出最少还需要建设的道路数目。

样例输入:
4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0
样例输出:
1
0
2
998

做这道题有两个思路,第一个思路是求出题目中非连通部分的数目,进一步求得答案。代码如下
 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <string>
 5 #define MAX 1002
 6 int map[MAX][MAX];
 7 int flag[MAX];
 8 
 9 void dfs(int start, int n) {
10     if(flag[start] == 0) {
11         flag[start] = 1;
12         for(int i = 1; i <= n; i++) {
13             if(flag[i] == 0 && (map[start][i] == 1)) {
14                 dfs(i, n);
15             }
16         }
17        
18     }
19     
20 }
21 int main(int argc, char const *argv[])
22 {
23     int n,m;
24     scanf("%d",&n);
25     while(n != 0) {
26         int count = 0;
27         scanf("%d",&m);
28         for(int i = 1; i <= n; i++) {
29             for(int j = 1; j <= n; j++) {
30                 map[i][j] = 0;
31             }
32             flag[i] = 0;
33         }
34         for(int i = 0; i < m; i++) {
35             int a,b;
36             scanf("%d %d",&a,&b);
37             map[a][b] = 1;
38             map[b][a] = 1;
39             
40         }
41         for(int i = 1; i <= n; i++) {
42             if(flag[i] == 0) {
43                 dfs(i, n);
44                 count++;
45             }
46             
47         }
48 
49         printf("%d\n",count-1);
50         scanf("%d",&n);
51     }
52 
53     return 0;
54 }

 

另一种更简便的方法如下,将每一个连通起来的点线性相连,每一个连通集合的最后一个next值是初始值,有多少个这样的值说明有多少个集合,代码如下
 1 #include <cstdio>
 2 #define MAX 1002
 3 int next[MAX];
 4 
 5 int find(int x) {
 6     while(next[x] != 0) {
 7         x = next[x];
 8     }
 9     return x;
10 }
11 
12 int main(int argc, char const *argv[])
13 {
14     int n,m;
15     scanf("%d",&n);
16     while(n != 0) {
17         scanf("%d",&m);
18         for(int i = 1; i <= n; i++) {
19             next[i] = 0;
20         }
21         for(int i = 0; i < m; i++) {
22             int a,b;
23             scanf("%d %d",&a,&b);
24             int fa = find(a);
25             int fb = find(b);
26             if(fa != fb) {
27                 next[fa] = fb;
28             }
29             
30         }
31          int count = 0;
32              for(int i = 1; i <= n; i++) {
33                  //printf("%d\t",next[i]);
34               if(next[i]== 0) count++;
35          }
36         // printf("\n");
37         printf("%d\n",count-1);
38         scanf("%d",&n);
39     }
40 
41     return 0;
42 }

 


其实第二种方法就是并查集
posted @ 2016-07-16 16:34  Jason杰  阅读(297)  评论(0编辑  收藏  举报