题目描述
Farmer John had just acquired several new farms! He wants to connect the farms with roads so that he can travel from any farm to any other farm via a sequence of roads; roads already connect some of the farms.
Each of the N (1 ≤ N ≤ 1,000) farms (conveniently numbered 1..N) is represented by a position (Xi, Yi) on the plane (0 ≤ Xi ≤ 1,000,000; 0 ≤ Yi ≤ 1,000,000). Given the preexisting M roads (1 ≤ M ≤ 1,000) as pairs of connected farms, help Farmer John determine the smallest length of additional roads he must build to connect all his farms.
Farmer John最近得到了一些新的农场,他想新修一些道路使得他的所有农场可以经过原有的或是新修的道路互达(也就是说,从任一个农场都可以经过一些首尾相连道路到达剩下的所有农场)。有些农场之间原本就有道路相连。 所有N(1 <= N <= 1,000)个农场(用1..N顺次编号)在地图上都表示为坐标为(X_i, Y_i)的点(0 <= X_i <= 1,000,000;0 <= Y_i <= 1,000,000),两个农场间道路的长度自然就是代表它们的点之间的距离。现在Farmer John也告诉了你农场间原有的M(1 <= M <= 1,000)条路分别连接了哪两个农场,他希望你计算一下,为了使得所有农场连通,他所需建造道路的最小总长是多少。
输入格式
* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: Two space-separated integers: Xi and Yi
* Lines N+2..N+M+2: Two space-separated integers: i and j, indicating that there is already a road connecting the farm i and farm j.
-
第1行: 2个用空格隔开的整数:N 和 M
-
第2..N+1行: 第i+1行为2个用空格隔开的整数:X_i、Y_i
-
第N+2..N+M+2行: 每行用2个以空格隔开的整数i、j描述了一条已有的道路, 这条道路连接了农场i和农场j
输出格式
* Line 1: Smallest length of additional roads required to connect all farms, printed without rounding to two decimal places. Be sure to calculate distances as 64-bit floating point numbers.
输出使所有农场连通所需建设道路的最小总长,保留2位小数,不必做 任何额外的取整操作。为了避免精度误差,计算农场间距离及答案时 请使用64位实型变量
输入输出样例
4 1 1 1 3 1 2 3 4 3 1 4
4.00
模板题。比较巧妙的一点就是,对于已经存在的边,直接令a[x][y] = a[y][x] = 0即可。
#include <bits/stdc++.h> using namespace std; double a[1005][1005], d[1005]; bool vis[1005] = { 0 }; int n, m; struct point { double x; double y; } p[1005]; double calc(point a, point b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } void prim() { int i, j, y; d[1] = 0; for(i = 1; i < n; i++) { int x = 0; for(j = 1; j <= n; j++) { if(!vis[j] && (x == 0 || d[j] < d[x])) x = j; } vis[x] = 1; for(y = 1; y <= n; y++) { if(!vis[y]) d[y] = min(d[y], a[x][y]); } } } int main() { int i, j; for(i = 1; i <= 1000; i++) { d[i] = 1e18; } cin >> n >> m; for(i = 1; i <= n; i++) { cin >> p[i].x >> p[i].y; } for(i = 1; i <= n; i++) { for(j = 1; j <= i; j++) { a[i][j] = a[j][i] = calc(p[i], p[j]); } } double ans = 0.0; for(i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); a[x][y] = a[y][x] = 0.0; } prim(); for(i = 2; i <= n; i++) { ans += d[i]; } printf("%.2lf", ans); return 0; }