EOJ 2067 Building Roads

http://www.acm.cs.ecnu.edu.cn/problem.php?problemid=2067poj 3625 http://poj.org/problem?id=3625
 

题目大意:有N个农场,现在给出他们的坐标,并且已经知道了有些农场他们之间是已经相连的了,现在问怎么连最小的边,能将这些农场都连接起来
解题思路:变相的最小生成树,即将已经连起来的边的权值置为-1,那么根据prim算法,优先选的就是那条-1边,这样我们在选边的时候,如果是-1边我们就可以不用加进来

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 using namespace std;
 6 
 7 #define MAXN 1005
 8 #define inf 1e12
 9 
10 struct Point
11 {
12     double x, y;
13 }point[MAXN];
14 
15 int n, m;
16 double map[MAXN][MAXN];
17 
18 double dist(Point a, Point b)
19 {
20     return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
21 }
22 
23 void prim()
24 {
25     int vis[MAXN], v;
26     double mi, d[MAXN];
27     for (int i = 1; i <= n; i++)
28     {
29         vis[i] = 0;
30         d[i] = map[1][i];
31     }
32     for (int i = 1; i <= n; i++)
33     {
34         mi = inf;
35         for (int j = 1; j <= n; j++)
36             if (!vis[j] && d[j] < mi)
37             {
38                 mi = d[j];
39                 v = j;
40             }
41         vis[v] = 1;
42         for (int j = 1; j <= n; j++)
43             if (!vis[j] && d[j] > map[v][j])
44                 d[j] = map[v][j];
45     }
46     d[0] = 0;
47     for (int i = 1; i <= n; i++)
48         if (d[i] != -1) d[0] += d[i];
49     printf("%.2f\n", d[0]);
50 }
51 
52 int main()
53 {
54     int a, b;
55     while (cin >> n >> m)
56     {
57         for (int i = 1; i <= n; i++)
58             scanf("%lf%lf", &point[i].x, &point[i].y);
59         for (int i = 1; i <= n; i++)
60             for (int j = 1; j <= n; j++)
61                 map[i][j] = map[j][i] = dist(point[i], point[j]);
62         for (int i = 1; i <= m; i++)
63         {
64             scanf("%d%d", &a, &b);
65             map[a][b] = map[b][a] = -1;
66         }
67         prim();
68     }
69     return 0;
70 }
View Code

 

posted on 2013-07-11 16:33  KimKyeYu  阅读(330)  评论(1编辑  收藏  举报

导航