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\n", 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\n", 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\n", 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\n", 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 }

 

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/Inkblots/p/5365977.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞