poj 2728(最优比率生成树 二分)

题目大意是:给你坐标上一些点,然后你需要用一些边把他们连接起来,边有费用和长度,求总费用和总长度最小比值。

  二分答案:

  每边有两权值(a,b),求∑a/ ∑b最小的生成树.

  设∑a/ ∑b=k  -->  ∑a=k*∑b  --->a1+a2+...an = k*(b1+b2+..bn) ---->∑(ai-k*bi)==0

  即边权变为a-k*b后求MST,看是否<0,如果<0则说明k太大了。>0说明k太小了。

ps:有种迭代的方法。看没太懂。下次看。

  1 // File Name: 2728.cpp
  2 // Author: Missa
  3 // Created Time: 2013/2/23 星期六 21:36:48
  4 
  5 #include<iostream>
  6 #include<cstdio>
  7 #include<cstring>
  8 #include<algorithm>
  9 #include<cmath>
 10 #include<queue>
 11 #include<stack>
 12 #include<string>
 13 #include<vector>
 14 #include<cstdlib>
 15 #include<map>
 16 #include<set>
 17 using namespace std;
 18 #define CL(x,v) memset(x,v,sizeof(x));
 19 #define R(i,st,en) for(int i=st;i<en;i++)
 20 const int maxn = 1e3+5;
 21 const int inf = 0x3f3f3f3f;
 22 const double eps = 1e-5;
 23 int n;
 24 struct Point
 25 {
 26     int x,y,z;
 27     Point(){}
 28     Point(int x,int y,int z):x(x),y(y),z(z){}
 29 };
 30 double h[maxn][maxn];//村子的高度差
 31 double g[maxn][maxn];//村子的距离
 32 double prim(int src,double k)//源点,二分的答案k
 33 {
 34     double ans=0.0;
 35     double dis[maxn];
 36     bool vis[maxn];
 37     R(i,1,n+1)
 38     {
 39         vis[i]=0;
 40         dis[i]=h[src][i]-k*g[src][i];
 41     }
 42     vis[src]=1;
 43     R(i,1,n)
 44     {
 45         double MIN=inf;
 46         int flag=-1;
 47         R(j,1,n+1)
 48         {
 49             if(!vis[j] && dis[j]<MIN)
 50             {
 51                 flag=j;
 52                 MIN=dis[j];
 53             }
 54         }
 55         if(flag==-1) break;
 56         vis[flag]=1;
 57         ans+=MIN;
 58         R(j,1,n+1)
 59             if(!vis[j] && h[flag][j]-k*g[flag][j]<dis[j])
 60                 dis[j]=h[flag][j]-k*g[flag][j];
 61     }
 62     return ans;
 63 }
 64 
 65 int main()
 66 {
 67     while(~scanf("%d",&n))
 68     {
 69         if(!n) break;
 70         int x,y,z,mx=0;
 71         vector<Point> v;
 72         v.clear();
 73         R(i,1,n+1)
 74         {
 75             scanf("%d%d%d",&x,&y,&z);
 76             v.push_back(Point(x,y,z));
 77             if(mx<z)
 78                 mx=z;
 79         }
 80         R(i,0,n)
 81             R(j,i,n)
 82             {
 83                 h[i+1][j+1]=h[j+1][i+1]=fabs(v[i].z-v[j].z);
 84                 g[i+1][j+1]=g[j+1][i+1]=sqrt((v[i].x-v[j].x)*(v[i].x-v[j].x) + (v[i].y-v[j].y)*(v[i].y-v[j].y));
 85             }
 86         /*R(i,1,n+1)
 87         {
 88             R(j,1,n+1)
 89             cout<<g[i][j]<<" ";
 90             cout<<endl;
 91         }*/
 92         /*
 93         double l=0.0,r=mx;
 94         while(r-l>eps)
 95         {
 96             double m=(l+r)/2.0;
 97             if(prim(1,m)<=0)
 98                 r=m;
 99             else
100                 l=m;
101         }
102         */
103         double l=0,r=0;
104         while(1)
105         {
106             l=prim(1,r);
107             if(fabs(l-r)<eps) break;
108             r=l;
109             cout<<l<<endl;
110         }
111         printf("%.3f\n",l);
112     }
113     return 0;
114 }

 

posted @ 2013-02-23 23:11  Missa  阅读(201)  评论(0编辑  收藏  举报