题目大意:给出一个完全图,图的边有两个权值: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
", ans);
}
return 0;
}