zoukankan      html  css  js  c++  java
  • ACM/ICPC 之 四道MST-Kruskal解法-练习题(POJ1251-POJ1287-POJ2031-POJ2421)

    由于题目简单,部分题意写在代码中(简单题就应该多练英文...),且较少给注释,需要注意的地方会写在代码中,虽然四个题意各有千秋,但万变不离其宗,细细思考一番会发现四道题都属于很直接的最小生成树问题,由于博主时间原因,暂提供Kruskal解法

    这四题可以作为最小生成树(MST)入门的上手题库


    POJ1251(ZOJ1406)-Jungle Roads

     1 //Kruskal-裸
     2 //POJ1251-ZOJ1406
     3 //找出维护道路的最小费用
     4 //Time:0Ms    Memory:168K
     5 #include<iostream>
     6 #include<cstring>
     7 #include<cstdio>
     8 #include<algorithm>
     9 using namespace std;
    10 
    11 #define MAXN 28
    12 #define MAXM 80
    13 
    14 struct Edge {
    15     int u, v;
    16     int d;
    17     friend bool operator < (Edge e1, Edge e2) { return e1.d < e2.d; }
    18 }e[MAXM];
    19 
    20 int n, m;
    21 int fa[MAXN];
    22 
    23 int Find(int x)
    24 {
    25     return fa[x] < 0 ? x : fa[x] = Find(fa[x]);
    26 }
    27 
    28 void Union(int r1,int r2)
    29 {
    30     int num = fa[r1] + fa[r2];
    31     if (r1 < r2)
    32     {
    33         fa[r2] = r1;
    34         fa[r1] = num;
    35     }
    36     else {
    37         fa[r1] = r2;
    38         fa[r2] = num;
    39     }
    40 }
    41 
    42 void kruskal()
    43 {
    44     int num = 0;
    45     int minroad = 0;
    46     memset(fa, -1, sizeof(fa));
    47     for (int i = 0; i < m; i++)
    48     {
    49         int r1 = Find(e[i].u);
    50         int r2 = Find(e[i].v);
    51         if (r1 == r2)    continue;
    52         minroad += e[i].d;
    53         Union(r1, r2);
    54         if (++num == n - 1) break;
    55     }
    56     printf("%d
    ", minroad);
    57 }
    58 
    59 int main()
    60 {
    61     while (scanf("%d", &n), n)
    62     {
    63         m = 0;
    64         for (int i = 1; i < n; i++)
    65         {
    66             int road;
    67             char city[2];
    68             scanf("%s%d", city, &road);    //用%c和getchar()会RE,可能是后台数据的问题
    69             while (road--)
    70             {
    71                 int d;
    72                 char c[2];
    73                 scanf("%s%d", c, &d);
    74                 e[m].u = city[0] - 'A';
    75                 e[m].v = c[0] - 'A';
    76                 e[m++].d = d;
    77             }
    78         }
    79         sort(e, e + m);
    80         kruskal();
    81     }
    82     return 0;
    83 }


    POJ1287(ZOJ1372)-Networking

     1 //Kruskal-须查重边
     2 //设计一个由给定所需网线长度的网络组成的最短网线方案(可能有重边)
     3 //POJ1287-ZOJ1372
     4 //Time:16Ms    Memory:192K
     5 #include<iostream>
     6 #include<cstring>
     7 #include<cstdio>
     8 #include<algorithm>
     9 using namespace std;
    10 
    11 #define MAXN 51
    12 
    13 struct Edge {
    14     int u, v;
    15     int d;
    16     friend bool operator < (Edge e1, Edge e2) { return e1.d < e2.d; }
    17 }e[MAXN*MAXN];
    18 
    19 int n, m;
    20 int fa[MAXN];
    21 int v[MAXN][MAXN];    //端点查边
    22 int minroad;
    23 
    24 int Find(int x)
    25 {
    26     return fa[x] < 0 ? x : fa[x] = Find(fa[x]);
    27 }
    28 
    29 void Union(int r1, int r2)
    30 {
    31     int num = fa[r1] + fa[r2];
    32     if (r1 < r2)
    33     {
    34         fa[r2] = r1;
    35         fa[r1] = num;
    36     }
    37     else {
    38         fa[r1] = r2;
    39         fa[r2] = num;
    40     }
    41 }
    42 
    43 void kruskal()
    44 {
    45     int num = 0;
    46     minroad = 0;
    47     memset(fa, -1, sizeof(fa));
    48     for (int i = 0; i < m; i++)
    49     {
    50         int r1 = Find(e[i].u);
    51         int r2 = Find(e[i].v);
    52         if (r1 == r2)    continue;
    53         Union(r1, r2);
    54         minroad += e[i].d;
    55         if (++num == n - 1) break;
    56     }
    57     printf("%d
    ", minroad);
    58 }
    59 
    60 int main()
    61 {
    62     while (scanf("%d", &n), n)
    63     {
    64         memset(v, -1, sizeof(v));
    65         scanf("%d", &m);
    66         for (int i = 0; i < m; i++)
    67         {
    68             scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].d);
    69             if (v[e[i].u][e[i].v] >= 0)    //查重
    70             {
    71                 e[v[e[i].u][e[i].v]].d = min(e[v[e[i].u][e[i].v]].d, e[i].d);
    72                 i--; m--;
    73             }
    74             else v[e[i].u][e[i].v] = i;
    75         }
    76         sort(e, e + m);
    77         kruskal();
    78     }
    79     return 0;
    80 }

    POJ2031(ZOJ1718)-Jungle Roads

     1 //Kruskal+去重叠+简单几何
     2 //题目不难,如果用到并查集,那么去重的部分需要考虑好
     3 //Time:32Ms    Memory:268K
     4 #include<iostream>
     5 #include<cstring>
     6 #include<cstdio>
     7 #include<cmath>
     8 #include<algorithm>
     9 using namespace std;
    10 
    11 #define MAXN 105
    12 #define POW2(x) ((x)*(x))
    13 #define DIS(i,j) (sqrt(POW2(v[i].x - v[j].x) + POW2(v[i].y - v[j].y) + POW2(v[i].z - v[j].z)))
    14 
    15 struct Vertex {
    16     double x, y, z;
    17     double r;
    18 }v[MAXN];
    19 
    20 struct Edge {
    21     int u, v;
    22     double d;
    23     friend bool operator < (Edge e1, Edge e2) { return e1.d < e2.d; }
    24 }e[MAXN*MAXN];
    25 
    26 int n, m;
    27 int fa[MAXN];
    28 
    29 int Find(int x)
    30 {
    31     return fa[x] < 0 ? x : fa[x] = Find(fa[x]);
    32 }
    33 
    34 void Union(int r1, int r2)
    35 {
    36     r1 = Find(r1);
    37     r2 = Find(r2);
    38     if (r1 == r2)    return;    //处理边的时候需要考虑,否则将RE
    39     int num = fa[r1] + fa[r2];
    40     if (r1 < r2)
    41     {
    42         fa[r2] = r1;
    43         fa[r1] = num;
    44     }
    45     else {
    46         fa[r1] = r2;
    47         fa[r2] = num;
    48     }
    49 }
    50 
    51 void kruskal()
    52 {
    53     int num = 0;
    54     double minroad = 0;
    55     for (int i = 0; i < m; i++)
    56     {
    57         int r1 = Find(e[i].u);
    58         int r2 = Find(e[i].v);
    59         if (r1 == r2)    continue;
    60         Union(r1, r2);
    61         minroad += e[i].d;
    62         if (++num == n - 1)    break;
    63     }
    64     printf("%.3lf
    ", minroad);
    65 }
    66 
    67 int main()
    68 {
    69     while (scanf("%d", &n), n)
    70     {
    71         m = 0;
    72         memset(fa, -1, sizeof(fa));
    73         for (int i = 0; i < n; i++)
    74         {
    75             scanf("%lf%lf%lf%lf", &v[i].x, &v[i].y, &v[i].z, &v[i].r);
    76             for (int j = 0; j < i; j++)
    77             {
    78                 double len = DIS(i, j) - v[i].r - v[j].r;
    79                 if (len <= 1e-5)
    80                     Union(i, j);    //可能r1与r2同集合-在Union中处理
    81                 else {
    82                     e[m].u = i;
    83                     e[m].v = j;
    84                     e[m++].d = len;
    85                 }
    86             }
    87         }
    88         sort(e, e + m);
    89         kruskal();
    90     }
    91     return 0;
    92 }

    POJ2421-Jungle Roads

     1 //Kruskal-略变形
     2 //Time:47Ms    Memory:272K
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<algorithm>
     7 using namespace std;
     8 #define MAX 105
     9 
    10 struct Edge {
    11     int u, v;
    12     int d;
    13     friend bool operator < (Edge e1, Edge e2) { return e1.d < e2.d; }
    14 }e[MAX*MAX/2];
    15 
    16 int n, m;
    17 int fa[MAX];
    18 int d[MAX][MAX];
    19 
    20 int Find(int x)
    21 {
    22     return fa[x] < 0 ? x : fa[x] = Find(fa[x]);
    23 }
    24 
    25 void Union(int r1, int r2)
    26 {
    27     r1 = Find(r1);
    28     r2 = Find(r2);
    29     if (r1 == r2)    return;
    30     int num = fa[r1] + fa[r2];
    31     if (fa[r1] < fa[r2])
    32     {
    33         fa[r2] = r1;
    34         fa[r1] = num;
    35     }
    36     else {
    37         fa[r1] = r2;
    38         fa[r2] = num;
    39     }
    40 }
    41 
    42 void kruskal()
    43 {
    44     int minroad = 0;
    45     int num = 0;
    46     for (int i = 0; i < m; i++)
    47     {
    48         int r1 = Find(e[i].u);
    49         int r2 = Find(e[i].v);
    50         if (r1 == r2)    continue;
    51         Union(r1, r2);
    52         minroad += e[i].d;
    53         if (++num == n - 1) break;
    54     }
    55     printf("%d
    ", minroad);
    56 }
    57 
    58 int main()
    59 {
    60     memset(fa, -1, sizeof(fa));
    61     scanf("%d", &n);
    62     for (int i = 1; i <= n; i++)
    63         for (int j = 1; j <= n; j++)
    64             scanf("%d", &d[i][j]);
    65     int k;
    66     scanf("%d", &k);
    67     while (k--)
    68     {
    69         int u, v;
    70         scanf("%d%d", &u, &v);
    71         Union(u, v);
    72     }
    73     m = 0;
    74     for (int i = 1; i <= n; i++)
    75         for (int j = 1; j < i; j++)
    76         {
    77             e[m].u = i;
    78             e[m].v = j;
    79             e[m++].d = d[i][j];
    80         }
    81     sort(e, e + m);
    82     kruskal();
    83     return 0;
    84 }
    他坐在湖边,望向天空,她坐在对岸,盯着湖面
  • 相关阅读:
    【开源】我和 JAP(JA Plus) 的故事
    justauth-spring-boot-starter V1.3.5 发布成功
    JustAuth 1.15.9 版发布,支持飞书、喜马拉雅、企业微信网页登录
    详细介绍如何自研一款"博客搬家"功能
    推荐一款自研的Java版开源博客系统OneBlog
    JavaScript常用方法
    Markdown 语法学习
    Sublime Text常用设置之个人配置
    webStorm常用设置之过滤文件夹
    HTTP详解
  • 原文地址:https://www.cnblogs.com/Inkblots/p/5365977.html
Copyright © 2011-2022 走看看