UVa 1494 - Qin Shi Huang's National Road System

链接

传送门

题意

给出\(n\)个城市的坐标和人口,现在要修建道路是所有城市连通,可以使用魔法造出一条路,设使用魔法造出的路的人口和为\(A\),剩余道路的修建长度为\(B\),输出\(A/B\)的最大值。

思路

首先构建mst求出修建mst的长度\(L\),然后预处理出mst中任意两点间的路径中最长边的长度。枚举使用魔法修建的道路连接的城市求得\(A\),在mst中减去链接的道路的最长边长\(B=L-maxcost[i][j]\)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;

const int maxn = 1010;
int x[maxn], y[maxn], p[maxn];
int fa[maxn], vis[maxn], visn;
double maxcost[maxn][maxn];
vector<int> G[maxn];
vector<double> W[maxn];
struct Edge {
int u, v;
double len;
bool operator < (const Edge& rhs) const {
return len < rhs.len;
}
} e[maxn * maxn];

int find(int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
}

void dfs(int u, int fa, double facost) {
for (int i = 0; i < visn; ++i) {
int x = vis[i];
maxcost[u][x] = maxcost[x][u] = max(maxcost[x][fa], facost);
}
vis[visn++] = u;
for(int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if(v != fa) {
dfs(v, u, W[u][i]);
}
}
}

int main() {
int t;
scanf("%d", &t);
while (t--) {
int n, m = 0;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
fa[i] = i;
scanf("%d%d%d", &x[i], &y[i], &p[i]);
}
for (int i = 1; i <= n; ++i) {
for (int j = i + 1; j <= n; ++j) {
e[m].u = i, e[m].v = j;
e[m].len = sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
++m;
}
}
sort(e, e + m);
fill(G, G + n + 1, vector<int>());
fill(W, W + n + 1, vector<double>());
int cnt = n;
double mstl = 0;
for (int i = 0; i < m; ++i) {
int fu = find(e[i].u), fv = find(e[i].v);
if (fu != fv) {
fa[fu] = fv;
G[e[i].u].push_back(e[i].v);
W[e[i].u].push_back(e[i].len);
G[e[i].v].push_back(e[i].u);
W[e[i].v].push_back(e[i].len);
mstl += e[i].len;
if (--cnt == 1) {
break;
}
}
}
visn = 0;
memset(maxcost, 0, sizeof maxcost);
dfs(1, -1, 0);
double ans = 0;
for (int i = 1; i <= n; ++i) {
for (int j = i + 1; j <= n; ++j) {
ans = max(ans, (p[i] + p[j]) / (mstl - maxcost[i][j]));
}
}
printf("%.2lf\n", ans);
}
return 0;
}