题意:
题解:最优比率生成树+分数规划
重新定义每条边权值为cost - mid * len,mid为总比例,跑mst,直到权值和为0,则为答案。mid即总比例用二分。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
using namespace std;
const int maxn = 1e3 + 5;
const double eps = 1e-6;
int n, mst[maxn], m;
double edge[maxn][maxn], lowcost[maxn], co[maxn][maxn];
double prim(double mid) {
int i, j, minid;
double sum = 0, min;
for (i = 1; i <= n; i++) {
lowcost[i] = co[1][i] - mid * edge[1][i];
mst[i] = 1;
}
mst[1] = 0;
for (i = 2; i <= n; i++) {
min = 0x3f3f3f3f;
minid = 0;
for (j = 1; j <= n; j++) {
if (lowcost[j] < min && mst[j] != 0) {
min = lowcost[j];
minid = j;
}
}
sum += lowcost[minid];
mst[minid] = 0;
for (j = 1; j <= n; j++) {
if (co[minid][j] - mid * edge[minid][j] < lowcost[j] && mst[j] != 0) {
lowcost[j] = co[minid][j] - mid * edge[minid][j];
}
}
}
return sum;
}
int x[maxn], y[maxn], z[maxn];
double dis(int xa, int ya, int xb, int yb) {
return sqrt((xa - xb) * (xa - xb) + (ya - yb) * (ya - yb));
}
int main() {
while (scanf("%d", &n) && n) {
for (int i = 1; i <= n; i++) scanf("%d%d%d", &x[i], &y[i], &z[i]);
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
edge[i][j] = edge[j][i] = dis(x[i], y[i], x[j], y[j]);
co[i][j] = co[j][i] = fabs(z[i] - z[j]);
}
}
double l = 0, r = 40;
while (r - l > eps) {
double mid = (l + r) / 2;
if (prim(mid) >= 0) l = mid;
else r = mid;
}
printf("%.3f\n", l);
}
return 0;
}