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

【Description】

David the Great has just become the king of a desert country. To win the respect of his people, he decided to build channels all over his country to bring water to every village. Villages which are connected to his capital village will be watered. As the dominate ruler and the symbol of wisdom in the country, he needs to build the channels in a most elegant way.
After days of study, he finally figured his plan out. He wanted the average cost of each mile of the channels to be minimized. In other words, the ratio of the overall cost of the channels to the total length must be minimized. He just needs to build the necessary channels to bring water to all the villages, which means there will be only one way to connect each village to the capital.
His engineers surveyed the country and recorded the position and altitude of each village. All the channels must go straight between two villages and be built horizontally. Since every two villages are at different altitudes, they concluded that each channel between two villages needed a vertical water lifter, which can lift water up or let water flow down. The length of the channel is the horizontal distance between the two villages. The cost of the channel is the height of the lifter. You should notice that each village is at a different altitude, and different channels can't share a lifter. Channels can intersect safely and no three villages are on the same line.
As King David's prime scientist and programmer, you are asked to find out the best solution to build the channels.

【Input】

There are several test cases. Each test case starts with a line containing a number N (2 <= N <= 1000), which is the number of villages. Each of the following N lines contains three integers, x, y and z (0 <= x, y < 10000, 0 <= z < 10000000). (x, y) is the position of the village and z is the altitude. The first village is the capital. A test case with N = 0 ends the input, and should not be processed.

【Output】

For each test case, output one line containing a decimal number, which is the minimum ratio of overall cost of the channels to the total length. This number should be rounded three digits after the decimal point.

【Sample Input】

4
0 0 0
0 1 1
1 1 2
1 0 3
0

【Sample Output】

1.000

【题意】

给出一张完全图,每条边都有长度和花费,要求在图中找到一棵生成树,使得Sum(Cost)/Sum(dist)达到最小。

【分析】

据说05年ACM的某场比赛上,教主怒切一题最优比率生成树,坑死了无数跟榜着...-_-////

最优比率生成树的前导知识是01分数规划。

基本思路是Dinkelbach逼近法:

整体思路跟原本的01分数规划基本相同,方程F(L)=Sum(cost[i])/Sum(dist[i]),只要把L'的生成过程改成Prim即可。

Prim堆加边的时候,用cost-l*dist作为边权。

 /* ***********************************************
MYID : Chen Fan
LANG : G++
PROG : PKU_2728
************************************************ */ #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <bitset> using namespace std; typedef struct nod
{
int x,y,z;
} node;
node p[]; double getdist(int i,int j)
{
return sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
} typedef struct enod
{
int x,y;
double dist,cost,r;
friend bool operator < (enod a,enod b)
{
return a.r>b.r;
}
} enode; enode gete(int x,int y,double dist,double cost,double l)
{
enode a;
a.x=x;a.y=y;a.dist=dist;a.cost=cost;
a.r=cost-l*dist;
return a;
} double prim(int n,double l)
{
priority_queue<enode> q;
while (!q.empty()) q.pop();
bitset<> flag;
flag.reset();
flag[]=;
double cost=,dist=;
for (int i=;i<=n;i++) q.push(gete(,i,getdist(,i),abs(p[].z-p[i].z),l)); for (int i=;i<n;i++)
{
enode now=q.top();
q.pop();
while (flag[now.y])
{
now=q.top();
q.pop();
}
flag[now.y]=;
cost+=now.cost;dist+=now.dist;
for (int j=;j<=n;j++)
if (j!=now.y&&!flag[j])
q.push(gete(now.y,j,getdist(now.y,j),abs(p[now.y].z-p[j].z),l));
} return cost/dist;
} int main()
{
freopen("2728.txt","r",stdin); int n;
while (scanf("%d",&n))
{
if (n==) break; for (int i=;i<=n;i++) scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z); double l=,ans;
while ()
{
ans=prim(n,l);
if (fabs(ans-l)<1e-) break;
else l=ans;
} printf("%.3f\n",ans);
} return ;
}

POJ 2728 Desert King 最优比率生成树的更多相关文章

  1. POJ.2728.Desert King(最优比率生成树 Prim 01分数规划 二分/Dinkelbach迭代)

    题目链接 \(Description\) 将n个村庄连成一棵树,村之间的距离为两村的欧几里得距离,村之间的花费为海拔z的差,求花费和与长度和的最小比值 \(Solution\) 二分,假设mid为可行 ...

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

    题意: 给定n个村子的坐标(x,y)和高度z, 求出修n-1条路连通所有村子, 并且让 修路花费/修路长度 最少的值 两个村子修一条路, 修路花费 = abs(高度差), 修路长度 = 欧氏距离 分析 ...

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

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

  4. POJ 2728 Desert King (最优比例生成树)

    POJ2728 无向图中对每条边i 有两个权值wi 和vi 求一个生成树使得 (w1+w2+...wn-1)/(v1+v2+...+vn-1)最小. 采用二分答案mid的思想. 将边的权值改为 wi- ...

  5. POJ2728 Desert King —— 最优比率生成树 二分法

    题目链接:http://poj.org/problem?id=2728 Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Subm ...

  6. Desert King(最优比率生成树)

    Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 22717   Accepted: 6374 Desc ...

  7. 【POJ2728】Desert King 最优比率生成树

    题目大意:给定一个 N 个点的无向完全图,边有两个不同性质的边权,求该无向图的一棵最优比例生成树,使得性质为 A 的边权和比性质为 B 的边权和最小. 题解:要求的答案可以看成是 0-1 分数规划问题 ...

  8. POJ2728 Desert King 最优比率生成树

    题目 http://poj.org/problem?id=2728 关键词:0/1分数规划,参数搜索,二分法,dinkelbach 参考资料:http://hi.baidu.com/zzningxp/ ...

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

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

随机推荐

  1. 使用queryperf对DNS服务器作压力测试

    一.querperf简介 当我们把DNS服务器配置好后,我们肯定会想测试一下DNS服务器的性能如何,上线后如果请求数够多服务器还能否响应?于是,我们可以使用软件模拟环境,对DNS服务器作评估性的测试. ...

  2. DataGirdView 编辑项时的验证

    dgvConfig.DataSource = CreateTable(); dgvConfig.Columns["编号"].ReadOnly = true; //只读 dgvCon ...

  3. 关于spring的注解方式注入默认值(转) -- 首字母小写

    1.是首字母小写 比如 UserAction对应的id是userAction 可以通过ApplicationContext 对象的act.getBean("userAction") ...

  4. 转: oracle 存储过程 执行动态 实现sql

    http://jingyan.baidu.com/article/5d6edee2fbb9f999eadeecb9.html http://jingyan.baidu.com/article/3638 ...

  5. cin详解(cin.get()、cin.getline()、cin.clear()、cin.sync())

    在C中,输入输出用scanf和printf,在输入数据的同时还需说明数据的类型,如果输入数据较多,那就很麻烦,而C++中也有相似的东西cin和cout,它们来自C++的一个名叫" iostr ...

  6. EGL接口介绍-----Android OpenGL ES底层开发

    引自:http://www.cnitblog.com/zouzheng/archive/2011/05/30/74326.html EGL 是 OpenGL ES 和底层 Native 平台视窗系统之 ...

  7. OpenCV 基础知识------图像创建、访问、转换

    cvCreateImage函数-- Cxcore数组操作 创建头并分配数据 IplImage* cvCreateImage( CvSize size, int depth, int channels ...

  8. linker command failed with exit code 1 (use -v to see invocation)修改方法

    它的意思是指文件丢失或者文件重复,你就要仔细查看项目中有没有重复的文件,如有重复修改即可,如果是文件丢失,那就麻烦啦!你需要根据报错的地方进行修补文件,最为直接的方法是重新创建项目.还有另外一种情况是 ...

  9. HDU 5718 Oracle

    如果非零的数小于等于1个,则无解.否则有解. 取出一个最小的非零的数作为一个数,剩下的作为一个数,相加即可. #include<cstdio> #include<cstring> ...

  10. 通过ReconstructMe实现3D扫描

    实物3D建模 目前在3D游戏制作过程中,需要专业人士花几天甚至数星期的时间,借助于Autodesk 3ds Max和Maya等昂贵的软件工具制作3D模型.纹理和动画.游戏制作中经常使用一种方法,即设计 ...