引用别人的解释:

题意:有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可,

建造水管距离为坐标之间的欧几里德距离(好象是叫欧几里德距离吧),费用为海拔之差

现在要求方案使得费用与距离的比值最小

很显然,这个题目是要求一棵最优比率生成树,

概念

有带权图G, 对于图中每条边e[i], 都有benifit[i](收入)和cost[i](花费), 我们要求的是一棵生成树T, 它使得 ∑(benifit[i]) / ∑(cost[i]), i∈T 最大(或最小).

这显然是一个具有现实意义的问题.

解法之一 0-1分数规划

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

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

为了使 r 最大, 设计一个子问题---> 让 z = ∑(benifit[i] * x[i]) - l * ∑(cost[i] * x[i]) = ∑(d[i] * x[i]) 最大 (d[i] = benifit[i] - l * cost[i]) , 并记为z(l). 我们可以兴高采烈地把z(l)看做以d为边权的最大生成树的总权值.

然后明确两个性质:

 1.  z单调递减

  证明: 因为cost为正数, 所以z随l的减小而增大.

 2.  z( max(r) ) = 0

  证明: 若z( max(r) ) < 0, ∑(benifit[i] * x[i]) - max(r) * ∑(cost[i] * x[i]) < 0, 可化为 max(r) < max(r). 矛盾;

          若z( max(r) ) >= 0, 根据性质1, 当z = 0 时r最大.

到了这个地步, 七窍全已打通, 喜欢二分的上二分, 喜欢Dinkelbach的就Dinkelbach.

复杂度

时间 O( O(MST) * log max(r) )

空间 O( O(MST) )

迭代+prim

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<limits.h>
#define MAX 1100
double x[MAX],y[MAX],z[MAX];
double cost[MAX][MAX],dist[MAX][MAX];
int n;
double prim(double);
int main(void)
{
int i,j;
while(scanf("%d",&n)&&n){
for(i=;i<=n;i++){//读取数据
scanf("%lf%lf%lf",&x[i],&y[i],&z[i]);
}
//处理 任意点之间的长度和价值
for(i=;i<=n;i++){
for(j=i+;j<=n;j++){
double d=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
dist[i][j]=dist[j][i]=sqrt(d);
double c=z[i]-z[j];
if(c<) c=-c;
cost[i][j]=cost[j][i]=c;
}
}
//判断给定的rate是否在误差之内
double a=,b=; //初始r为0
while()
{
b = prim(a);
if(fabs(a-b)<1e-) break;
a=b;
}
printf("%.3lf\n",b); }
return ;
}
double prim(double p)
{
int visit[MAX],father[MAX];
double dis[MAX];
int i,j;
//访问数组初始化
memset(visit,,sizeof(visit));
visit[]=;
//对已加入的最小生成树的顶点集合 计算它的父节点
for(i=;i<=n;i++){
dis[i]=cost[][i]-p*dist[][i];
father[i]=;
} int k=;
double totalCost=,totalDist=;
//prim求最小生成树
for(i=;i<n;i++){
k=;
double mincost=INT_MAX;//最大值,最好是这个 for(j=;j<=n;j++){
if(!visit[j]&&dis[j]<mincost) {
mincost=dis[j];k=j;
}
} if(k==) break; visit[k]=;
totalCost+=cost[ father[k] ][k];
totalDist+=dist[ father[k] ][k]; for(j=;j<=n;j++){
double h=cost[k][j]-p*dist[k][j];
if(!visit[j]&&dis[j]>h){
dis[j]=h;
father[j]=k;
}
} }
return totalCost/totalDist;
}

poj 2728 Desert King(最小比率生成树,迭代法)的更多相关文章

  1. poj 2728 Desert King (最小比例生成树)

    http://poj.org/problem?id=2728 Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissio ...

  2. Desert King 最小比率生成树 (好题)

    Description David the Great has just become the king of a desert country. To win the respect of his ...

  3. poj 2728 Desert King (最优比率生成树)

    Desert King http://poj.org/problem?id=2728 Time Limit: 3000MS   Memory Limit: 65536K       Descripti ...

  4. POJ 2728 Desert King(最优比例生成树 二分 | Dinkelbach迭代法)

    Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 25310   Accepted: 7022 Desc ...

  5. POJ 2728 Desert King 最优比率生成树

    Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 20978   Accepted: 5898 [Des ...

  6. POJ 2728 Desert King(最优比率生成树 01分数规划)

    http://poj.org/problem?id=2728 题意: 在这么一个图中求一棵生成树,这棵树的单位长度的花费最小是多少? 思路: 最优比率生成树,也就是01分数规划,二分答案即可,题目很简 ...

  7. POJ 2728 Desert King ★(01分数规划介绍 && 应用の最优比率生成树)

    [题意]每条路径有一个 cost 和 dist,求图中 sigma(cost) / sigma(dist) 最小的生成树. 标准的最优比率生成树,楼教主当年开场随手1YES然后把别人带错方向的题Orz ...

  8. POJ 2728 Desert King (最优比率树)

    题意:有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可,建造水管距离为坐标之间的欧几里德距离,费用为海拔之差,现在要求方案使得费用与距离的比值最小,很显然,这个题目 ...

  9. POJ 2728 Desert King (01分数规划)

    Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissions:29775   Accepted: 8192 Descr ...

随机推荐

  1. C++中输入输出流及文件流操作笔记

    1.流的控制 iomanip          在使用格式化I/O时应包含此头文件.    stdiostream   用于混合使用C和C + +的I/O机制时,例如想将C程序转变为C++程序 2.类 ...

  2. Qt for Linux:环境搭建(CentOS 6.5 32位)——完全从零安装

    正文开始前,我们假设,用户可以操作终端 拥有root权限,以下所有操作也均由root完成 可以上网 安装了CentOS 6.5 32位 注:红色部分,每个人可能都不一样 话不多说,列出本章大致流程 1 ...

  3. CCNA实验(1) -- 基本配置

    Ctrl+A: 到行首(Ahead)Ctrl+E: 到行尾(End)Esc+B: 回退一个单词(Back)Esc+F: 前进一个单词(Forward) 1.三种配置模式2.时间时区配置3.设置超时时间 ...

  4. 传智播客C/C++学院年薪24-50万招聘C/C++讲师

    C/C++技术讲师 6名 (北京,年薪:24-50万) 传智播客C/C++课程培训体系如下: 1.C语言,世界五百强C语言面试训练 2.C++语言,世界五百强C++语言面试训练 3.数据结构与算法,世 ...

  5. DBCP|C3P0参数详解

    1.<!-- 数据源1 --> 2. <bean id="dataSource" 3. class="org.apache.commons.dbcp.B ...

  6. Crisis of HDU(母函数)

    Crisis of HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  7. JSP简单练习-获取表单数据

    在JSP中,server端程序与client交互最经常使用的方法就是採用表单提交数据.表单提交的方法主要有两种,一种是get方法.还有一种是post方法.两者最大的差别:使用get方法提交的数据会显示 ...

  8. MySQL学习笔记(4)

    插入记录① INSERT [INTO] tbl_name [(col_name,-)] {VALUES | VALUE} ({expr | DEFAULT},-),(-),- 可以用表达式或者DEFA ...

  9. 红豆带你从零学C#系列之:使用集合组织相关数据

    ArrayList(数组列表) Why:如果一个公司有5名员工,一般我们会用长度为5的对象数组来存储信息,但要是有新员工来了,5个长度的数组就不够用了,因此我们需要一种能够根据需要自动分配容量的动态数 ...

  10. Mac上小巧实用的GIF格式录屏软件 LICEcap

    LICEcap 是一款小巧使用的Mac屏幕录制软件,它以GIF格式来录制屏幕内容,用户可以自定帧率和录制范围.这样就能控制生成文件的大小,非常便捷实用哦.点击进入下载 <ignore_js_op ...