zoukankan      html  css  js  c++  java
  • 九度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
    ",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	",next[i]);
    34               if(next[i]== 0) count++;
    35          }
    36         // printf("
    ");
    37         printf("%d
    ",count-1);
    38         scanf("%d",&n);
    39     }
    40 
    41     return 0;
    42 }

    其实第二种方法就是并查集
  • 相关阅读:
    汇编笔记
    PHP笔记——SOAP
    Eclipse 插件资源地址记录
    使用SetWindowLong修改窗口样式
    C++ builder 剪贴板Clipboard使用
    c++ builder 实现右键选择节点实现方式
    c++ builder 使listview获得焦点并选择第一个节点
    c++ builder 2009 启用codeguard 检测内存泄漏
    c++ builder 2009如何生成独立运行exe
    WPF编程学习——样式
  • 原文地址:https://www.cnblogs.com/jasonJie/p/5676772.html
Copyright © 2011-2022 走看看