zoukankan      html  css  js  c++  java
  • POJ 2728 Desert King (最优比例生成树)

    POJ2728 无向图中对每条边i 有两个权值wi 和vi 求一个生成树使得 (w1+w2+...wn-1)/(v1+v2+...+vn-1)最小。

    采用二分答案mid的思想。

    将边的权值改为 wi-vi*mid.

    对所有边求和后除以v 即为 (w1+w2+...wn-1)/(v1+v2+...+vn-1)-mid. 因此,若当前生成树的权值和为0,就找到了答案。否则更改二分上下界。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    
    const int maxn=1000;
    int n;
    double lenth[maxn],nowans,lef,righ,w[maxn][maxn],v[maxn][maxn];
    bool intree[maxn];
    
    double ab(double x)
    {
     if(x>0)return x;
     	else return x*(-1);
    }
    
    class point
    {
     public:
     double x;double y;double z;
    };
    
    
    point po[maxn];
    
    double dist(point a,point b);
    
    
    
    
    double cost(point a,point b)
    {
     return ab((a.z-b.z));
    }
    
    
    class edge
    {
     public:
     int  pa;int pb;
     double dis;double cos;double div;	
     edge(int a,int b,double(*distance)(point,point),double (*cost)(point,point))
     {
      this->pa=a;this->pb=b;
      this->dis=distance(po[a],po[b]);
      this->cos=cost(po[a],po[b]);
      this->div=cos/dis;
     }
     bool operator <(const edge b)const
     {
      return (this->cos-(this->dis*nowans))>(b.cos-(b.dis*nowans));//这个算法的核心 
     }
    };
    
    double dist(point a,point b)
    {
     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    
    double min(double a,double b)
    {
     if(a<b)return a;
     	else return b;
    }
    
    
    
    
    int main()
    {
     ios::sync_with_stdio(false);
     while(cin>>n)
     {
       if(n==0)return 0;
       lef=0.0;righ=1e6;
       for(int i=0;i<n;i++)
        	{
     	     cin>>po[i].x>>po[i].y>>po[i].z;
    	    }
      for(int i=0;i<n;i++)
      	for(int j=0;j<n;j++)
      		{
      		 w[i][j]=cost(po[i],po[j]);
      		 v[i][j]=dist(po[i],po[j]);
    		}
       double minnow;
      while(true)
       	{
       	 nowans=(lef+righ)/2;minnow=0;
       	 memset(intree,0,sizeof(intree));
       	 for(int i=1;i<n;i++)
       	 	{
       	 	 lenth[i]=w[0][i]-v[0][i]*nowans;
    		}
       	 lenth[0]=0.0;intree[0]=true;
       	 for(int i=1;i<n;i++)
       	 	{
       	 	 double temp=1e+30;int tj=0;
       	 	 for(int j=1;j<n;j++)
       	 	 	if(!intree[j]&&lenth[j]<temp)
       	 	 		{
       	 	 		 tj=j;
       	 	 		 temp=lenth[j];
    				}
    		 minnow+=lenth[tj];
    		 intree[tj]=true;
    		 for(int j=1;j<n;j++)
    		 	{
    		 	 if(!intree[j])lenth[j]=min(lenth[j],w[tj][j]-v[tj][j]*nowans);
    			}
    		}
    	 if(ab(minnow-0.0)<1e-5)break;
    	 if(minnow>0)lef=nowans;
    	 	else righ=nowans;
    	}
      printf("%.3lf
    ",(lef+righ)/2);
     }
     return 0;
    }
    

      用二分答案思想解决的生成树问题还有单度限制最小生成树,参考CODEFORCES 125E.

  • 相关阅读:
    初始化mysql数据库 /usr/bin/mysql_install_db执行时报错
    CentOS7安装mysql兼容性问题
    CentOS7网络连接问题以及重启网络服务失败
    CentOS7安装nginx
    zookeeper启动时报错:Error contacting service. It is probably not running问题
    CentOS查看卸载openjdk
    使用yum命令时提示:Another app is currently holding the yum lock
    修改eclipse中文件打开默认方式
    [程序员代码面试指南]链表问题-单链表的选择排序(选择排序)
    [程序员代码面试指南]链表问题-删除无序链表中重复出现的节点
  • 原文地址:https://www.cnblogs.com/heisenberg-/p/6399833.html
Copyright © 2011-2022 走看看