• hdoj1102 Constructing Roads(Prime || Kruskal)


    题目链接

    http://acm.hdu.edu.cn/showproblem.php?pid=1102

    题意

    有n个村庄(编号1~n),给出n个村庄之间的距离,开始时n个村庄之间已经有了q条路,现在需要修一条路,这条路连接起所有的村庄,求在已经存在的路径的基础上,最少还需要修多长的路。

    思路

    普通最小生成树是从零开始构造一棵最小生成树,而这题开始时图中已经有了一些路径,那这些路就不需要被修了,所以将这些路的修理长度置为0,然后使用Prime算法或者Kruskal算法求解即可。

    代码

    Prime算法:

     1 #include <algorithm>
     2 #include <cstring>
     3 #include <cstdio>
     4 using namespace std;
     5 
     6 const int INF = 0x7fffffff;
     7 const int N = 100 + 10;
     8 int map[N][N];
     9 int dist[N];    //记录从起点到其余各点的长度,不断更新
    10 int n, q;
    11 
    12 void prime()
    13 {
    14     int min_edge, min_node;
    15     for (int i = 1; i <= n; i++)
    16         dist[i] = INF;
    17     int ans = 0;
    18     int now = 1;
    19     for (int i = 1; i < n;i++)
    20     {
    21         min_edge = INF;
    22         dist[now] = -1;
    23         for (int j = 1; j <= n; j++)
    24         {
    25             if (j != now && dist[j] >= 0)
    26             {
    27                 if (map[now][j] >= 0)    //注意是map[now][j]>=0,因为有些路已经修好了,初始化时令其长度为0
    28                     dist[j] = min(dist[j], map[now][j]);
    29                 if (dist[j] < min_edge)
    30                 {
    31                     min_edge = dist[j];    //min_edge存储与当前结点相连的最短的边
    32                     min_node = j;
    33                 }
    34             }
    35         }
    36         ans += min_edge;    //ans存储最小生成树的长度
    37         now = min_node;
    38     }
    39     printf("%d
    ", ans);
    40 }
    41 
    42 int main()
    43 {
    44     //freopen("hdoj1102.txt", "r", stdin);
    45     while (scanf("%d", &n) == 1)
    46     {
    47         memset(map, 0, sizeof(map));
    48         for (int i = 1; i <= n;i++)
    49             for (int j = 1; j <= n; j++)
    50                 scanf("%d", &map[i][j]);
    51         scanf("%d", &q);
    52         int a, b;
    53         for (int i = 0; i < q; i++)
    54         {
    55             scanf("%d%d", &a, &b);
    56             map[a][b] = map[b][a] = 0;
    57         }
    58         prime();
    59     }
    60     return 0;
    61 }

    Kruskal算法:

     1 #include <algorithm>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <vector>
     5 using namespace std;
     6 
     7 struct Edge
     8 {
     9     int a, b, dist;
    10 
    11     Edge() {}
    12     Edge(int a, int b, int d) :a(a), b(b), dist(d) {}
    13     bool operator < (Edge edge)    //将边按边长从短到长排序
    14     {
    15         return dist < edge.dist;
    16     }
    17 };
    18 
    19 const int N = 100 + 10;
    20 int p[N];    //并查集使用
    21 int map[N][N];
    22 vector<Edge> v;
    23 int n, q;
    24 
    25 int find_root(int x)
    26 {
    27     if (p[x] == -1)
    28         return x;
    29     else return find_root(p[x]);
    30 }
    31 
    32 void kruskal()
    33 {
    34     memset(p, -1, sizeof(p));
    35     sort(v.begin(), v.end());
    36     int ans = 0;
    37     for (int i = 0; i < v.size(); i++)
    38     {
    39         int ra = find_root(v[i].a);
    40         int rb = find_root(v[i].b);
    41         if (ra != rb)
    42         {
    43             ans += v[i].dist;
    44             p[ra] = rb;
    45         }
    46     }
    47     printf("%d
    ", ans);
    48 }
    49 
    50 int main()
    51 {
    52     //freopen("hdoj1102.txt", "r", stdin);
    53     while (scanf("%d", &n) == 1)
    54     {
    55         v.clear();
    56         int t;
    57         for (int i = 1; i <= n; i++)
    58             for (int j = 1; j <= n; j++)
    59                 scanf("%d", &map[i][j]);
    60         scanf("%d", &q);
    61         int a, b;
    62         for (int i = 0; i < q; i++)
    63         {
    64             scanf("%d%d", &a, &b);
    65             map[a][b] = map[b][a] = 0;
    66         }
    67 
    68         for (int i = 1; i <= n; i++)
    69             for (int j = 1; j <= n; j++)
    70                 if (j > i)    v.push_back(Edge(i, j, map[i][j]));
    71 
    72         kruskal();
    73     }
    74     return 0;
    75 }

    注意点

    这题是有多组输入数据的,如果只按一组输入数据处理的话会WA.

  • 相关阅读:
    sqlserver sql优化案例及思路
    mysql执行计划常用说明
    MYSQL 的rownum
    innodb crash
    spring-mybatis源码追踪
    mylyn提交到JIRA的日期格式错误
    [google面试CTCI] 2-1.移除链表中重复元素
    [google面试CTCI] 2-0.链表的创建
    [google面试CTCI] 1-8.判断子字符串
    [google面试CTCI] 1-7.将矩阵中特定行、列置0
  • 原文地址:https://www.cnblogs.com/sench/p/7966384.html
Copyright © 2020-2023  润新知