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. weblogic找不到数据源

     查看weblogic日志 报错是每个数据源都找不到. 查看oracle用户状态 select username,account_status,lock_date from dba_users;  解 ...

  2. 那些年我们一起追逐的多线程(Thread、ThreadPool、委托异步调用、Task/TaskFactory、Parallerl、async和await)

    一. 背景 在刚接触开发的头几年里,说实话,根本不考虑多线程的这个问题,貌似那时候脑子里也有没有多线程的这个概念,所有的业务都是一个线程来处理,不考虑性能问题,当然也没有考虑多线程操作一条记录存在的并 ...

  3. SHELL:多文件的重命名和移动

    rename find mv #实现查找png 和 jpeg文件 #!/bin/bash #file name: rename.sh #use: rename.jpg  and .png files ...

  4. uwsgi+anaconda+nginx部署django项目(ubuntu下)

    conda 环境不必多说: conda(或source)  activate  test 进入test虚拟环境 接下来安装uwsgi: pip install uwsgi 在conda环境下大概率安装 ...

  5. 挖矿病毒、ddos入侵流程及溯源

    一 挖矿病毒简介  攻击者利用相关安全隐患向目标机器种植病毒的行为. 二 攻击方式 攻击者通常利用弱口令.未授权.代码执行.命令执行等漏洞进行传播.示例如下: 示例1:   POST /tmUnblo ...

  6. 2018-2019-2 20175306实验一《Java开发环境的熟悉》实验报告

    2018-2019-2 20175306实验一<Java开发环境的熟悉>实验报告 一.实验内容及步骤 实验一 Java开发环境的熟悉-1 ·建立有自己学号的实验目录. ·通过vim Hel ...

  7. Python爬虫之selenium各种注意报错

    刚刚写完第一个selenuim+BeautifulSoup实战爬虫 爬淘宝.发现代码写完后不加for 翻页的时候没什么问题 解析 操作 都没问题 也就是说第一页 的内容 完好 pagebtn=wait ...

  8. 清北学堂2019NOIP提高储备营DAY1

    今天是第二次培训的第一天,关于NOIP的基础算法,主要内容如下: $1.枚举 $2.搜索 $3.贪心 $1.枚举: •定义: 枚举又叫做穷举,是一种基础的算法,其思路主要是:从问题中有可能的解集中一一 ...

  9. HDU - 1036

    题意描述很垃圾,后来看别人代码才知道怎么回事:对(题目所给d/总时间:所有时间加起来)四舍五入并取整,然后对结果/60得到用了几分钟:对结果%60得到用了几秒. presentation error一 ...

  10. 封装selenium自动化框架中的截图功能

    对selenium自带的截图功能进行封装: 以下为封装的代码,自定义一个.py文件即可,图片路径自己设置一个. #coding:utf-8 class Screen(object): ''' 封装的截 ...