POJ2728 Desert King 最优比率生成树
题目大意:给出一个完全图,图的边有两个权值:len和cost。现要求一个生成树,能够连通所有节点,且cost的和与len的和的比值最小。
二分法枚举lambda,把每个边权改为len-cost*lambda求最小生成树。得出的边权和若等于0,则lambda为所求。否则,若大于0,则取右子区间;若小于零,则取左子区间。
注意:精度应当比所求精度再精确两位小数。
#include <cstdio> #include <cmath> #include <algorithm> using namespace std; //#define test #define way1 #define Eps 1e-6 #define INF 0x3f3f3f3f #define LOOP(a,b) for(int a=1; (a)<=(b); a++) const int MAX_NODE = 1010; int Cost[MAX_NODE][MAX_NODE], X[MAX_NODE], Y[MAX_NODE], Z[MAX_NODE]; double Dist[MAX_NODE][MAX_NODE]; double Lambda; double GetCost(int z1, int z2) { return abs(z1 - z2); } double GetDist(int x1, int y1, int x2, int y2) { double a1 = x1, b1 = y1, a2 = x2, b2 = y2; return sqrt((a1 - a2)*(a1 - a2) + (b1 - b2)*(b1 - b2)); } struct PrimMatrix { bool InTree[MAX_NODE]; double LowLen[MAX_NODE]; int _vCount; double Len(int u, int v) { return (double)Cost[u][v] - Lambda*(double)Dist[u][v]; } void Init(int vCount) { _vCount = vCount; } double Proceed() { int cnt = 1; double ans = 0; memset(InTree, false, sizeof(InTree)); memset(LowLen, INF, sizeof(LowLen)); InTree[1] = true; LOOP(v, _vCount) { LowLen[v] = Len(1,v); } LOOP(i, _vCount) { int u; double lowLen = INF; LOOP(j, _vCount) { if (!InTree[j] && LowLen[j] < lowLen) { lowLen = LowLen[j]; u = j; } } if (lowLen == INF) break; cnt++; ans += lowLen; InTree[u] = true; LOOP(v, _vCount) if (!InTree[v] && Len(u,v) < LowLen[v]) LowLen[v] = Len(u,v); } return cnt == _vCount ? ans : -1; } }g; double Procedure(double lambda) { Lambda = lambda; return g.Proceed(); } bool Judge(double lambda) { return Procedure(lambda) < 0; } double Bsearch(double l, double r) { double ans = -1, mid; while (r - l > Eps) { mid = (l + r) / 2; if (Judge(mid)) r = ans = mid; else l = mid; } return ans; } void Init() { LOOP(u, g._vCount) LOOP(v, g._vCount) { Cost[u][v] = GetCost(Z[u], Z[v]); Dist[u][v] = GetDist(X[u], Y[u], X[v], Y[v]); } } int main() { int totNode; while (scanf("%d", &totNode) && totNode) { g.Init(totNode); LOOP(i, totNode) scanf("%d%d%d", i + X, i + Y, i + Z); Init(); //double r = Procedure(0); double ans = Bsearch(0, 100000); printf("%.3f\n", ans); } return 0; }