ACM/ICPC 之 四道MST-Prim解法(POJ1258-POJ1751-POJ2349-POJ3026)

  四道MST,适合Prim解法,也可以作为MST练习题。

  题意包括在代码中。



POJ1258-Agri Net

  水题

 1 //Prim-没什么好说的
 2 //接受一个邻接矩阵,求MST
 3 //Time:0Ms    Memory:220K
 4 #include<iostream>
 5 #include<cstring>
 6 #include<cstdio>
 7 #include<algorithm>
 8 using namespace std;
 9 #define MAX 105
10 #define INF 0x3f3f3f3f
11 int n, m;
12 int d[MAX][MAX];
13 int lowcost[MAX];
14 bool v[MAX];
15 void prim()
16 {
17     int minroad = 0;
18     memset(v, false, sizeof(v));
19     v[0] = true;
20     for (int i = 1; i < n; i++)
21         lowcost[i] = d[i][0];
22     for (int i = 1; i < n; i++)
23     {
24         double mind = INF;
25         int k;
26         for (int j = 1; j < n; j++)
27         {
28             if (!v[j] && mind > lowcost[j])
29             {
30                 mind = lowcost[j];
31                 k = j;
32             }
33         }
34
35         minroad += lowcost[k];
36         v[k] = true;
37         for (int j = 1; j < n; j++)
38             if (!v[j])    lowcost[j] = min(d[k][j], lowcost[j]);
39     }
40     printf("%d\n", minroad);
41 }
42 int main()
43 {
44     while (scanf("%d", &n) != EOF)
45     {
46         for (int i = 0; i < n; i++)
47             for (int j = 0; j < n; j++)
48                 scanf("%d", &d[i][j]);
49         prim();
50     }
51     return 0;
52 }


POJ1751(ZOJ2048)-Highways

 1 //Prim-好题
 2 //ZOJ2048-POJ1751
 3 //ZOJ中多组样例,两个样例间有一个空格(否则会WA)
 4 //需要记录上一个节点-注意内存限制在10^4K内
 5 //有M个城市已经有通路,输出让N个城市生成最短通路的各边,Special Judge-输出次序不定
 6 //Time:94Ms    Memory:4648K
 7 #include<iostream>
 8 #include<cstring>
 9 #include<cstdio>
10 #include<cmath>
11 #include<algorithm>
12 using namespace std;
13
14 #define MAX 755
15 #define INF 0x3f3f3f3f
16 #define POW2(x) ((x)*(x))
17 #define DIS(i,j) (sqrt(POW2(p[i][0] - p[j][0]) + POW2(p[i][1] - p[j][1])))
18
19 int n, m;
20 double p[MAX][2];
21 int fa[MAX];    //记录上一个顶点
22 double d[MAX][MAX];
23 double lowcost[MAX];
24 bool v[MAX];
25
26 void prim()
27 {
28     memset(v, false, sizeof(v));
29     v[1] = true;
30     for (int i = 2; i <= n; i++)
31     {
32         lowcost[i] = d[i][1];
33         fa[i] = 1;
34     }
35     for (int i = 2; i <= n; i++)
36     {
37         double mind = INF;
38         int k;
39         for (int j = 2; j <= n; j++)
40         {
41             if (!v[j] && mind > lowcost[j])
42             {
43                 mind = lowcost[j];
44                 k = j;
45             }
46         }
47         if (mind > 1e-5)
48             printf("%d %d\n", fa[k], k);
49
50         v[k] = true;
51         for (int j = 2; j <= n; j++)
52         {
53             if (!v[j] && lowcost[j] > d[k][j])
54             {
55                 lowcost[j] = d[k][j];
56                 fa[j] = k;
57             }
58         }
59     }
60 }
61
62 int main()
63 {
64     scanf("%d", &n);
65     for (int i = 1; i <= n; i++)
66     {
67         scanf("%lf%lf", &p[i][0], &p[i][1]);
68         for (int j = 1; j < i; j++)
69             d[i][j] = d[j][i] = DIS(i, j);
70     }
71     scanf("%d", &m);
72     for (int i = 0; i < m; i++)
73     {
74         int v1, v2;
75         scanf("%d%d", &v1, &v2);
76         d[v1][v2] = d[v2][v1] = 0;
77     }
78     prim();
79     return 0;
80 }


POJ2349(ZOJ1914)-Arctic Network

 1 //Prim
 2 //POJ2349-ZOJ1914
 3 //有n个前哨可以通过卫星通信(无距离限制),总共m个前哨,相互通信可以通过无线电通信(有距离限制),求所需无线电信号最短距离
 4 //定理:如果去掉所有权值大于d的边后,最小生成树被分割成为k个连通支,图也被分割成为k个连通支(可尝试证明)
 5 //Time:47Ms    Memory:2164K
 6 #include<iostream>
 7 #include<cstring>
 8 #include<cstdio>
 9 #include<cmath>
10 #include<algorithm>
11 using namespace std;
12
13 #define MAX 501
14 #define INF 0x3f3f3f3f
15 #define POW2(x) ((x)*(x))
16 #define DIS(i,j) (sqrt(POW2(p[i][0] - p[j][0]) + POW2(p[i][1] - p[j][1])))
17
18 int n, m;
19 double p[MAX][2];    //point
20 double d[MAX][MAX];    //distance
21 double lowcost[MAX];
22 bool v[MAX];
23
24 void prim()
25 {
26     memset(lowcost, 0, sizeof(lowcost));
27     memset(v, false, sizeof(v));
28     v[0] = true;
29     for (int i = 1; i < m; i++)
30         lowcost[i] = d[i][0];
31     for (int i = 1; i < m; i++)
32     {
33         int mind = INF;
34         int k;
35         for (int j = 1; j < m; j++)
36         {
37             if (!v[j] && mind > lowcost[j])
38             {
39                 mind = lowcost[j];
40                 k = j;
41             }
42         }
43         v[k] = true;
44         for (int j = 1; j < m; j++)
45             if(!v[j]) lowcost[j] = min(d[k][j], lowcost[j]);
46     }
47 }
48
49 int main()
50 {
51     int T;
52     scanf("%d", &T);
53     while (T--)
54     {
55         scanf("%d%d", &n, &m);
56         for (int i = 0; i < m; i++)
57         {
58             scanf("%lf%lf", &p[i][0], &p[i][1]);
59             for (int j = 0; j < i; j++)
60                 d[i][j] = d[j][i] = DIS(i, j);
61         }
62
63         prim();
64         sort(lowcost, lowcost + m);
65         printf("%.2lf\n", lowcost[m - n]);
66         //G++需要使用printf("%.2f\n", lowcost[m-n]);
67         //原因查了半天,好像是因为新版GCC标准中将%f和%lf合并为%f的意思
68     }
69     return 0;
70 }


POJ3026-Borg Maze

  1 //Prim+BFS
  2 //总是心想着要创造一个新算法,结果越想越麻烦...
  3 //保险做法:找出每个点间的距离,再进行Prim
  4 //Time:79Ms    Memory:292K
  5 #include<iostream>
  6 #include<cstring>
  7 #include<cstdio>
  8 #include<queue>
  9 #include<algorithm>
 10 using namespace std;
 11
 12 #define MAX 125        //MAX 50的话会RE或WA(博主在55RE,在100WA)
 13
 14 struct Point{
 15     int x, y;
 16     int step;
 17 }p;
 18
 19 int r, c;
 20 char board[MAX][MAX];
 21 int d[MAX][MAX];
 22 int num[MAX][MAX], cnt;
 23 int lowcost[MAX];
 24 bool v[MAX][MAX];
 25 int mov[4][2] = { {1,0}, {-1,0}, {0,1}, {0,-1} };
 26
 27 void bfs(Point p)
 28 {
 29     memset(v, false, sizeof(v));
 30     v[p.x][p.y] = true;
 31     int np = num[p.x][p.y];
 32     queue<Point> q;
 33     p.step = 0;
 34     q.push(p);
 35     while (!q.empty())
 36     {
 37         Point cur = q.front();
 38         q.pop();
 39         for (int i = 0; i < 4; i++)
 40         {
 41             Point t = cur;
 42             t.x += mov[i][0];
 43             t.y += mov[i][1];
 44             if (t.x > 0 && t.y > 0 && t.x < r && t.y < c && !v[t.x][t.y])
 45             {
 46                 if (board[t.x][t.y] == ‘#‘)    continue;
 47                 int nt = num[t.x][t.y];
 48                 t.step++;
 49                 v[t.x][t.y] = true;
 50                 if (board[t.x][t.y] == ‘A‘ || board[t.x][t.y] == ‘S‘)
 51                     d[nt][np] = t.step;
 52                 q.push(t);
 53             }
 54         }
 55     }
 56 }
 57
 58 void prim()
 59 {
 60     int v[MAX];
 61     memset(v, false, sizeof(v));
 62     memset(lowcost, 0x3f, sizeof(lowcost));
 63     v[0] = true;
 64     for (int i = 1; i < cnt; i++)
 65         lowcost[i] = d[i][0];
 66
 67     int minv = 0;
 68     for (int i = 1; i < cnt; i++)
 69     {
 70         int mind = 0x3f3f3f3f;
 71         int k;
 72         for (int j = 1; j < cnt; j++)
 73         {
 74             if (!v[j] && mind > lowcost[j])
 75             {
 76                 mind = lowcost[j];
 77                 k = j;
 78             }
 79         }
 80         minv += mind;
 81         v[k] = true;
 82         for (int j = 1; j < cnt; j++)
 83             if (!v[j]) lowcost[j] = min(lowcost[j], d[k][j]);
 84     }
 85     printf("%d\n", minv);
 86 }
 87
 88 int main()
 89 {
 90     int T;
 91     scanf("%d", &T);
 92     while (T--)
 93     {
 94         cnt = 0;
 95         scanf("%d%d", &c, &r);
 96         gets_s(board[0]);
 97         for (int i = 0; i < r; i++)
 98         {
 99             gets_s(board[i], MAX);
100             for (int j = 0; j < c; j++)
101                 if (board[i][j] == ‘S‘ || board[i][j] == ‘A‘)
102                     num[i][j] = cnt++;
103         }
104         for (int i = 0; i < r; i++)
105             for (int j = 0; j < c;j++)
106                 if (board[i][j] == ‘S‘ || board[i][j] == ‘A‘)
107                 {
108                     p.x = i; p.y = j;
109                     bfs(p);
110                 }
111         prim();
112     }
113     return 0;
114 }
时间: 2024-10-02 19:51:58

ACM/ICPC 之 四道MST-Prim解法(POJ1258-POJ1751-POJ2349-POJ3026)的相关文章

ACM/ICPC 之 判别MST唯一性-Kruskal解法(POJ1679)

判别MST是否唯一的例题. POJ1679-The Unique MST 题意:给定图,求MST(最小生成树)是否唯一,唯一输出路径长,否则输出Not Unique! 题解:MST是否唯一取决于是否有两边权值相同(其中一条边在第一次求得的MST内,另一条在MST外)的情况. 如果存在这样的边,则需要逐次删除MST内的该边,再次求MST,如果此次求得的MST路长与第一次MST相同,则确实存在不唯一的MST 否则,一定不存在多条MST. 1 //Kruskal-判断MST是否唯一 2 //Time:

ACM/ICPC 之 Prim范例(ZOJ1586-POJ1789(ZOJ2158))

两道Prim解法范例题型,简单的裸Prim,且两题相较以边为重心的Kruskal解法而言更适合以点为重心扩展的Prim解法. ZOJ1586-QS Network 题意:见Code 题解:直接的MST题型,本题的图为稠密图,因此适合以点为扩展导向的Prim算法(代码量也较少). 大抵是先以某点A为中心,标记点A,访问其邻接点,更新全图到该点的距离(不通路以INF表示),找出最短距离的点B 标记最短距离的B点,然后访问其邻接点,更新邻接点到B点的最短距离,找出最短距离的点C...以此类推... 将

【转】[email&#160;protected]&#183;ACM/ICPC 回忆录

转自:http://hi.baidu.com/ordeder/item/2a342a7fe7cb9e336dc37c89 2009年09月06日 星期日 21:55 初识ACM最早听说ACM/ICPC这项赛事是在大三上的算法课上张老师提到的,当时我们学校的组织参加这项活动才刚刚起步,我也没太在意,总觉得那是非常遥远的事,事实上当时我也从未相当如今我们能获得现在的成绩.真正踏入ACM/ICPC这个神奇的世界,不得不提到2004那一年我们学校的参赛队伍xmutank,正是听了pipo师兄的精彩演讲以

2016 ACM/ICPC Asia Regional Dalian Online 1006 /HDU 5873

Football Games Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 439    Accepted Submission(s): 157 Problem Description A mysterious country will hold a football world championships---Abnormal Cup

[转]浅谈ACM ICPC的题目风格和近几年题目的发展

斯坦福大学 王颖 ACM ICPC的比赛形式一般是五个小时八个题目,综合考察选手的数学能力.算法能力.coding能力和debug能力,还有团队配合能力.数学方面主要强调组合数学.图论和数论这三个方面的能力:而算法的覆盖范围很广,涉及了大部分经典的算法,和少量较前沿的算法.由于每道题目都需要通过所有的测试数据才能得分,并且需要精确解,这限制了Approximation algorithm在一些NP-hard的题目中的运用,从而使得搜索和剪枝策略对于NP-hard的题目非常重要. Final的题目

ZOJ 1586 QS Network (经典MST~Prim)

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=586 In the planet w-503 of galaxy cgb, there is a kind of intelligent creature named QS. QScommunicate with each other via networks. If two QS want to get connected, they need to buy two n

ACM:最小生成树,kruskal &amp;&amp; prim,并查集

题目: 输入顶点数目,边的数目,输入每条边的两个顶点编号还有每条边的权值,求最小生成树,输出最小生成树的权值.. 注意:prim算法适合稠密图,其时间复杂度为O(n^2),其时间复杂度与边得数目无关,而kruskal算法的时间复杂度为O(eloge)跟边的数目有关,适合稀疏图. kruskal----归并边:prim----归并点 方法一:kruskal,克鲁斯卡尔,并查集实现. #include <iostream> #include <algorithm> using name

HDU 1102 &amp;&amp; POJ 2421 Constructing Roads (经典MST~Prim)

链接:http://poj.org/problem?id=2421  或   http://acm.hdu.edu.cn/showproblem.php?pid=1102 Problem Description There are N villages, which are numbered from 1 to N, and you should build some roads such that every two villages can connect to each other. We

2016 ACM/ICPC亚洲区青岛站现场赛(部分题解)

摘要 本文主要列举并求解了2016 ACM/ICPC亚洲区青岛站现场赛的部分真题,着重介绍了各个题目的解题思路,结合详细的AC代码,意在熟悉青岛赛区的出题策略,以备战2018青岛站现场赛. HDU 5984 Pocky 题意 给出一根棒子(可以吃的)的长度x和切割过程中不能小于的长度d,每次随机的选取一个位置切开,吃掉左边的一半,对右边的棒子同样操作,直至剩余的长度不大于d时停止.现在给出x和d,问切割次数的数学期望是多少. 解题思路 当看到第二个样例2 1时,结果是1.693147,联想到ln