链接:
http://poj.org/problem?id=2728
题意:
给你n个点,每两个点之间有value和cost,找一个最小生成树,使得∑cost/∑value最小
题解:
典型的分数规划题,二分+最小生成树就可以了
代码:
31 struct point { double x, y, z; }p[MAXN]; 32 double a[MAXN][MAXN]; 33 double b[MAXN][MAXN]; 34 double cost[MAXN][MAXN]; 35 double d[MAXN]; 36 bool used[MAXN]; 37 int n; 38 39 double prim() { 40 rep(i, 0, n) d[i] = 1e20; 41 memset(used, 0, sizeof(used)); 42 d[0] = 0; 43 double res = 0; 44 45 while (1) { 46 int v = -1; 47 rep(u, 0, n) if (!used[u] && (v == -1 || d[u] < d[v])) v = u; 48 if (v == -1) break; used[v] = 1; res += d[v]; 49 rep(u, 0, n) d[u] = min(d[u], cost[v][u]); 50 } 51 return res; 52 } 53 54 double sqr(double x) { 55 return x*x; 56 } 57 58 bool check(double x) { 59 rep(i, 0, n) rep(j, 0, n) 60 cost[i][j] = -x * a[i][j] + b[i][j]; 61 return prim() >= 0; 62 } 63 64 int main() { 65 ios::sync_with_stdio(false), cin.tie(0); 66 while (cin >> n, n) { 67 rep(i, 0, n) cin >> p[i].x >> p[i].y >> p[i].z; 68 rep(i, 0, n) rep(j, 0, n) { 69 a[i][j] = sqrt(sqr(p[i].x - p[j].x) + sqr(p[i].y - p[j].y)); 70 b[i][j] = fabs(p[i].z - p[j].z); 71 } 72 double l = 0, r = 100; 73 rep(i, 0, 20) { 74 double m = (l + r) / 2; 75 if (check(m)) l = m; 76 else r = m; 77 } 78 printf("%.3f\n", l); 79 } 80 return 0; 81 }