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 }

 

你可能感兴趣的:(poj)