zoukankan      html  css  js  c++  java
  • 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
    ", ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    phpspider爬虫框架的使用
    【php设计模式】责任链模式
    【php设计模式】策略模式
    【php设计模式】观察者模式
    【php设计模式】模板模式
    【温故知新】php 魔术方法
    【php设计模式】享元模式
    Java50道经典习题-程序18 乒乓球赛
    Java50道经典习题-程序19 输入行数打印菱形图案
    Java50道经典习题-程序20 求前20项之和
  • 原文地址:https://www.cnblogs.com/headboy2002/p/8681562.html
Copyright © 2011-2022 走看看