【题意】:求最小比率生成树。

【题解】:最小比率生成树和01分数规划都是从这里学到的。
               最小比率生成树的模型其实就是01分数规划,关于01分数规划的资料,网上一大堆。
               简单说下做法,就是构造一个01分数规划的式子,然后变形,利用MST求取当前的最小值。
               然后利用二分或者Dinkelbach逼近到最优解即为答案。

【代码】:
 1 #include "iostream"
 2 #include "cstdio"
 3 #include "cstring"
 4 #include "algorithm"
 5 #include "vector"
 6 #include "queue"
 7 #include "cmath"
 8 #include "string"
 9 #include "cctype"
10 #include "map"
11 #include "iomanip"
12 using namespace std;
13 #define pb push_back
14 #define lc(x) (x << 1)
15 #define rc(x) (x << 1 | 1)
16 #define lowbit(x) (x & (-x))
17 #define ll long long
18 #define maxn 1050
19 #define eps 1e-6
20 
21 int n;
22 double d[maxn][maxn];
23 int cost[maxn][maxn];
24 
25 struct Point {
26     double x, y;
27     int z;
28 }p[maxn];
29 
30 double getdist(Point &a, Point &b) {
31     return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
32 }
33 
34 int getcost(Point &a, Point &b) {
35     return abs(a.z - b.z);
36 }
37 
38 double prim(int s, double &l) {
39     double anslen = 0.0, anscost = 0.0;
40     bool visit[maxn];
41     double dist[maxn], tmp, ans = 0.0;
42     int pre[maxn];
43     for(int i = 0; i < n; i++) visit[i] = false, dist[i] = 1e30;
44     dist[s] = 0.0, pre[s] = s;
45     while(1) {
46         int u = -1;
47         for(int i = 0; i < n; i++) {
48             if(!visit[i] && (u == -1 || dist[i] < dist[u])) u = i;
49         }
50         if(u == -1) break;
51         anscost += cost[pre[u]][u];
52         anslen += d[pre[u]][u];
53         ans += dist[u];
54         visit[u] = true;
55         for(int i = 0; i < n; i++) {
56             if(!visit[i] && (tmp = 1.0 * cost[u][i] - l * d[u][i]) < dist[i])
57                 dist[i] = tmp, pre[i] = u;
58         }
59     }
60     l = anscost / anslen;
61     return ans;
62 }
63 
64 void solve() {
65     double ans= 0.0, tmp = 0.0;
66     while(1) {
67         double tmp = prim(0, ans);
68         if(fabs(tmp) < eps) break;
69     }
70     printf("%.3f\n", ans);
71 }
72 
73 int main() {
74     while(scanf("%d", &n) && n) {
75         for(int i = 0; i < n; i++) {
76             scanf("%lf%lf%d", &p[i].x, &p[i].y, &p[i].z);
77             for(int j = 0; j < i; j++) {
78                 d[i][j] = d[j][i] = getdist(p[i], p[j]);
79                 cost[i][j] = cost[j][i] = getcost(p[i], p[j]);
80             }
81         }
82         solve();
83     }
84     return 0;
85 }
86