zoukankan      html  css  js  c++  java
  • poj2728+最优比率生成树

    题意:一个无向图,每条边有两个权值,h和l,要求一个生成树,使得所有边的h的和比上l的和最小。

    设x[i]等于1或0, 表示边e[i]是否属于生成树.

    则我们所求的比率       r = ∑(benifit[i] * x[i]) / ∑(cost[i] * x[i]), 0≤i<m .

    为了使 r 最小, 设计一个子问题---> 让     z = ∑(benifit[i] * x[i]) - k * ∑(cost[i] * x[i]) = ∑(d[i] * x[i]) 最小 (d[i] = benifit[i] - k * cost[i]) , 并记为z(k). 我们可以把z(k)看做以d为边权的最小生成树的总权值.(如果求r最大应该使用最大生成树).

    由于cost[i]>0,所以k增大则z减小,z在k上单调递减。

    接下来便是二分k

    当z<0,即k>∑(benifit[i] * x[i])/∑(cost[i] * x[i]).而我们要求k尽量大z才会小,这样k无上限,矛盾。

    故z应>=0,由于z在k上单调递减,所以要使r最小,则z要最小,则k要最大,k不能大到使z<0,所以k最大大到使z=0.

    二分k使z=0即可。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<cstdlib>
     6 using namespace std;
     7 struct node
     8 {
     9     double x,y,h;
    10 }p[1100];
    11 double g[1100][1100],l[1100][1100],h[1100][1100];
    12 double dis(double x1,double y1,double x2,double y2)
    13 {
    14     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
    15 }
    16 const double mmax=1<<30;
    17 double prim(int n)
    18 {
    19     int pre[1100],vis[1100],i;
    20     double lowcost[1100];
    21     memset(vis,0,sizeof(vis));
    22     vis[1]=1;
    23     for(i=1;i<=n;i++)
    24     {
    25         pre[i]=1;
    26         lowcost[i]=g[1][i];
    27     }
    28     int num=0;
    29     double sum=0;
    30     while(num<n-1)
    31     {
    32         double mmin=mmax;
    33         int vx;
    34         for(i=1;i<=n;i++)
    35         {
    36             if(!vis[i]&&lowcost[i]<mmin)
    37             {
    38                 mmin=lowcost[i];
    39                 vx=i;
    40             }
    41         }
    42         vis[vx]=1;
    43         num++;
    44         sum+=g[vx][pre[vx]];
    45         for(i=1;i<=n;i++)
    46         {
    47             if(!vis[i]&&g[vx][i]<lowcost[i])
    48             {
    49                 lowcost[i]=g[vx][i];
    50                 pre[i]=vx;
    51             }
    52         }
    53     }
    54     return sum;
    55 }
    56 int main()
    57 {
    58     int n,i,j;
    59     while(scanf("%d",&n)!=EOF&&n!=0)
    60     {
    61         for(i=1;i<=n;i++)
    62         scanf("%lf %lf %lf",&p[i].x,&p[i].y,&p[i].h);
    63         double minl=mmax,minh=mmax,maxl=-mmax,maxh=-mmax;
    64         for(i=1;i<=n;i++)
    65         {
    66              for(j=i;j<=n;j++)
    67              {
    68                  if(i==j)
    69                  {
    70                      l[i][j]=0;
    71                      h[i][j]=0;
    72                  }
    73                  else
    74                  {
    75                      l[i][j]=l[j][i]=dis(p[i].x,p[i].y,p[j].x,p[j].y);
    76                      h[i][j]=h[j][i]=fabs(p[i].h-p[j].h);
    77                      if(l[i][j]>maxl) maxl=l[i][j];
    78                  if(l[i][j]<minl) minl=l[i][j];
    79                  if(h[i][j]>maxh) maxh=h[i][j];
    80                  if(h[i][j]<minh) minh=h[i][j];
    81                  }
    82              }
    83         }
    84         double ll=minh/maxl;
    85         double rr=maxh/minl;
    86         while(rr-ll>1e-4)
    87         {
    88             double mid=(ll+rr)/2;
    89             for(i=1;i<=n;i++)
    90                 for(j=i;j<=n;j++)
    91                     g[i][j]=g[j][i]=h[i][j]-mid*l[i][j];
    92                     double ans=prim(n);
    93             if(ans>0)   ll=mid;
    94             else rr=mid;
    95         }
    96         printf("%.3f\n",ll);
    97     }
    98     return 0;
    99 }
  • 相关阅读:
    【前端_js】前端跨网络异步获取资源——fetch()
    【前端_React】React小书
    【前端_js】JQuery DataTables插件的使用
    【前端_js】解决ajax跨域请求数据
    event.srcElement在火狐(FireFox)下的兼容问题。搜索框获得焦点时默认文字变化
    ASP.NET MVC 上传大文件时404
    使用Zen coding高效编写html代码
    CSS 去除列表项li前面的小圆点
    谈谈CSS的布局,display、position、float
    JS引用类型之——RegExp
  • 原文地址:https://www.cnblogs.com/mt522/p/5285435.html
Copyright © 2011-2022 走看看