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;
}

  

posted @ 2018-03-31 11:44  headboy2002  阅读(96)  评论(0编辑  收藏  举报