EOJ 2067 Building Roads
题目大意:有N个农场,现在给出他们的坐标,并且已经知道了有些农场他们之间是已经相连的了,现在问怎么连最小的边,能将这些农场都连接起来
解题思路:变相的最小生成树,即将已经连起来的边的权值置为-1,那么根据prim算法,优先选的就是那条-1边,这样我们在选边的时候,如果是-1边我们就可以不用加进来
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }