First, what is the problem to be solved: a fully Weighted Graph with each edge having its own cost value cost [I] and benefit value benifit [I]? if X [I] is used to represent an edge or not, a spanning tree is obtained. Requirements: r = (Σ cost [I] * X [I])/(Σ benifit [I] * X [I]) minimum.
Typical question: poj2728-desert king
How to solve the problem: here we use the 0-1 score planning idea. The above formula can be transformed to Z (R) = Sigma cost [I] * X [I]-R * Sigma benifit [I] * X [I]. While Z (R) = 0 is what we want.
Here is a very important conclusion: Z (R) is a monotonic decreasing function, so it is linear. So "we can happily regard Z (r) as the total weight of the Minimum Spanning Tree with cost [I]-R * benifit [I] As the edge weight ". Obviously, the request is Z (max (R) = 0. Here, Max (R) is determined by Z = 0.
There are two algorithms:
1. dinkelbanch algorithm, that is, iteration method. Take an initial value of R, which is generally 0. After a spanning tree is obtained, r = (Σ benifit [I] * X [I]) /(Σ cost [I] * X [I]), after iteration of ...... R tends to the maximum value, while Z tends to 0.
2. the binary method. If Z (R) = 0 is what we want, and it is a monotonic function, then binary R is enough. It is said that binary is much slower than iteration.
Template dinkelbach poj 2728:
#include <iostream>#include <cstdio>#include <cmath>#include <vector>#include <cstring>#include <algorithm>#include <string>#include <set>#include <ctime>#include <queue>#include <map>#include <sstream>#define CL(arr, val) memset(arr, val, sizeof(arr))#define REP(i, n) for((i) = 0; (i) < (n); ++(i))#define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i))#define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i))#define L(x) (x) << 1#define R(x) (x) << 1 | 1#define MID(l, r) (l + r) >> 1#define Min(x, y) x < y ? x : y#define Max(x, y) x < y ? y : x#define E(x) (1 << (x))const double eps = 1e-6;typedef long long LL;using namespace std;const int N = 1<<10;const int inf = ~0u>>2;struct node { int x, y, z;} point[N];double cost[N][N];double benifit[N][N];double mi[N];int pre[N];bool vis[N];double c, d;int n;double prim(double ans) { int i, j, f; double mx; c = d = 0; for(i = 1; i < n; ++i) { mi[i] = cost[0][i] - ans*benifit[0][i]; pre[i] = 0; vis[i] = false; } mi[0] = 0; vis[0] = true; for(i = 0; i < n - 1; ++i) { mx = inf; f = 0; for(j = 0; j < n; ++j) { if(!vis[j] && mx > mi[j]) { mx = mi[j]; f = j; } } c += cost[pre[f]][f]; d += benifit[pre[f]][f]; vis[f] = true; for(j = 1; j < n; ++j) { double val = cost[f][j] - ans*benifit[f][j]; if(!vis[j] && mi[j] > val) { pre[j] = f; mi[j] = val; } } } return c/d;}int iabs(int x) { return x < 0 ? -x : x;}void init() { int i, j; for(i = 0; i < n; ++i) { for(j = 0; j < n; ++j) { cost[i][j] = iabs(point[i].z - point[j].z); benifit[i][j] = sqrt(1.*(point[i].x - point[j].x)*(point[i].x - point[j].x) + 1.*(point[i].y - point[j].y)*(point[i].y - point[j].y)); } }}void solve() { double ans = 0, tmp; while(1) { tmp = prim(ans); if(fabs(ans - tmp) < eps) break; else ans = tmp; } printf("%.3f\n", ans);}int main() { freopen("data.in", "r", stdin); int i; while(scanf("%d", &n), n) { for(i = 0; i < n; ++i) { scanf("%d%d%d", &point[i].x, &point[i].y, &point[i].z); } init(); solve(); } return 0;}