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

题意:n个村庄,每个村庄给你x、y、z坐标,表示他的三维位置,两个村庄之间距离为不算z轴欧几里得距离、建一条路的花费
为两个村庄z坐标差值,构建一条路网络,使的每个点都被连接(生成树),且让其花费/距离最小(01分数规划) 思路:二分比例,然后用最小(最大)生成树,比较是否符合情况。
例如:花费/距离<=mid == 花费-mid*距离 <= 0, 使用最小生成树(边权:花费-mid*距离),看看是否和小于零(满足) 注:我用前向星不知道为什么超时了,看网上题解改的邻接矩阵,知道的大佬orz请通知一声
 #include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#define inf 1e18;
using namespace std; int n;
int x[],y[],z[];
const double eps = 1e-; bool vis[];
double maps[][];
double cost[][]; double dis(int i,int j)
{
return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
} double dist[]; bool prim(double mid)
{
memset(vis,,sizeof(vis));
for(int i=;i<=n;i++)dist[i]=inf;
dist[]=;
for(int i=;i<n;i++)
{
int minn = inf;
int id = -;
for(int j=;j<=n;j++)
{
if(!vis[j] && (id == - || dist[j] < dist[id]))id=j;
}
if(id == -)break;
vis[id]=; for(int j=;j<=n;j++)
{
if(!vis[j])dist[j] = min(dist[j],cost[id][j]-mid*maps[id][j]);
}
}
double ans = ;
for(int i=;i<=n;i++)ans += dist[i];
if(ans <= )return ;
return ;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
memset(maps,,sizeof(maps));
for(int i=;i<=n;i++)
{
scanf("%d%d%d",&x[i],&y[i],&z[i]);
}
for(int i=;i<=n;i++)
{
for(int j=i+;j<=n;j++)
{
maps[i][j] = maps[j][i] = dis(i,j);
cost[i][j] = cost[j][i] = abs(z[i]-z[j]);
}
}
double l=,r=;
while(r - l >= eps)
{
double mid =(r-l)/+l;
if(prim(mid))r = mid;
else l = mid;
}
printf("%.3f\n",(l+r)/);
}
}

前向星超时代码:

 #include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#define inf 1e18;
using namespace std; int n;
int x[],y[],z[];
const double eps = 1e-;
struct Node
{
int y,next;
double val,c;
}node[];
int cnt,head[];
bool vis[]; void add(int x,int y,double val,double c)
{
node[++cnt].y=y;
node[cnt].val=val;
node[cnt].c=c;
node[cnt].next=head[x];
head[x]=cnt;
} double dis(int i,int j)
{
return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
} double dist[]; bool prim(double mid)
{
memset(vis,,sizeof(vis));
for(int i=;i<=n;i++)dist[i]=inf;
dist[]=;
for(int i=;i<n;i++)
{
int minn = inf;
int id = -;
for(int j=;j<=n;j++)
{
if(!vis[j] && (id == - || dist[j] < dist[id]))id=j;
}
if(id == -)break;
vis[id]=;
for(int j=head[id];j;j=node[j].next)
{
int to = node[j].y;
if(!vis[to])dist[to] = min(dist[to],node[j].c-mid*node[j].val);
}
}
double ans = ;
for(int i=;i<=n;i++)ans += dist[i];
if(ans <= )return ;
return ;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
cnt = ;
//printf("================================\n");
memset(head ,,sizeof(head));
for(int i=;i<=n;i++)
{
scanf("%d%d%d",&x[i],&y[i],&z[i]);
}
for(int i=;i<=n;i++)
{
for(int j=i+;j<=n;j++)
{
double td = dis(i,j);
double tz = abs(z[i]-z[j]);
add(i,j,td,tz);
add(j,i,td,tz);
}
}
double l=,r=;
while(r - l >= eps)
{
double mid =(r-l)/+l;
if(prim(mid))r = mid;
else l = mid;
}
printf("%.3f\n",(l+r)/);
}
}

Desert King POJ - 2728(最优比率生产树/(二分+生成树))的更多相关文章

  1. Desert King (poj 2728 最优比率生成树 0-1分数规划)

    Language: Default Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 22113   A ...

  2. [POJ2728] Desert King 解题报告(最优比率生成树)

    题目描述: David the Great has just become the king of a desert country. To win the respect of his people ...

  3. poj 2728 最优比率生成树

    思路:设sum(cost[i])/sum(dis[i])=r;那么要使r最小,也就是minsum(cost[i]-r*dis[i]);那么就以cost[i]-r*dis[i]为边权重新建边.当求和使得 ...

  4. poj 3621(最优比率环)

    题目链接:http://poj.org/problem?id=3621 思路:之前做过最小比率生成树,也是属于0/1整数划分问题,这次碰到这道最优比率环,很是熟悉,可惜精度没控制好,要不就是wa,要不 ...

  5. POJ 3621-Sightseeing Cows-最优比率环|SPFA+二分

    最优比率环问题.二分答案,对于每一个mid,把节点的happy值归类到边上. 对于每条边,用mid×weight减去happy值,如果不存在负环,说明还可以更大. /*---------------- ...

  6. poj 3621(最优比率环)

    Sightseeing Cows Farmer John has decided to reward his cows for their hard work by taking them on a ...

  7. POJ 3621 最优比率生成环

    题意:      让你求出一个最优比率生成环. 思路:      又是一个01分化基础题目,直接在jude的时候找出一个sigma(d[i] * x[i])大于等于0的环就行了,我是用SPFA跑最长路 ...

  8. poj 2728 最优比例生成树(01分数规划)模板

    /* 迭代法 :204Ms */ #include<stdio.h> #include<string.h> #include<math.h> #define N 1 ...

  9. POJ 2728 JZYZOJ 1636 分数规划 最小生成树 二分 prim

    http://172.20.6.3/Problem_Show.asp?id=1636 复习了prim,分数规划大概就是把一个求最小值或最大值的分式移项变成一个可二分求解的式子. #include< ...

随机推荐

  1. 电梯系列——OO Unit2分析和总结

    一.摘要 本文是BUAA OO课程Unit2在课程讲授.三次作业完成.自测和互测时发现的问题,以及倾听别人的思路分享所引起个人的一些思考的总结性博客.主要包含设计策略.代码度量.BUG测试和心得体会等 ...

  2. 关于读取XML文件代码【学习笔记】

    public class XmlManager { private XmlDocument m_XMLDoc = null; public XmlManager(XmlDocument xmldoc) ...

  3. 蓝桥杯入门训练-Fibonacci数列

    刚刚开始刷题的时候就栽了个大跟头,稍微记一下...... 一开始不是很理解:“我们只要能算出这个余数即可,而不需要先计算出Fn的准确值,再将计算的结果除以10007取余数,直接计算余数往往比先算出原数 ...

  4. 深入理解line-height与vertical-align——前端布局常用属性

    line-height.font-size.vertical-align是设置行内元素布局的关键属性.这三个属性是相互依赖的关系,改变行间距离.设置垂直对齐等都需要它们的通力合作.下面将主要介绍lin ...

  5. 解决无法打开myeclipse-->“The default workspace'D: /myeclipse spaceis in use or cannot be created. Please choose a different one”

    解决方法:到工作空间中删除.metadata文件夹中的.lock文件 如果提示无法删除,到任务管理器中关闭java进程:

  6. 优化算法:AdaGrad | RMSProp | AdaDelta | Adam

    0 - 引入 简单的梯度下降等优化算法存在一个问题:目标函数自变量的每一个元素在相同时间步都使用同一个学习率来迭代,如果存在如下图的情况(不同自变量的梯度值有较大差别时候),存在如下问题: 选择较小的 ...

  7. day13 闭包及装饰器

    """ 今日内容: 1.函数的嵌套定义及必包 2.global 与 nonlocal 关键字 3.开放封闭原则及装饰器 """ " ...

  8. 项目Alpha冲刺(1/10)

    1.项目燃尽图 2.今日进度描述 项目进展 熟悉Android Studio的基本使用,阅读代码规范 问题困难 学习中存在许多问题. 心得体会 应该选择一个自己熟悉的平台进行开发. 3.会议照片 4. ...

  9. SkyReach 团队团队展示

    班级:软件工程1916|W 作业:团队作业第一次-团队展示 团队名称:SkyReach 目标:展示团队风采,磨合团队 队员姓名与学号 队员学号 队员姓名 个人博客地址 备注 221600107 陈某某 ...

  10. 使用scrapy爬虫,爬取17k小说网的案例-方法一

    无意间看到17小说网里面有一些小说小故事,于是决定用爬虫爬取下来自己看着玩,下图这个页面就是要爬取的来源. a 这个页面一共有125个标题,每个标题里面对应一个内容,如下图所示 下面直接看最核心spi ...