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】

  1. 4
  2. 0 0 0
  3. 0 1 1
  4. 1 1 2
  5. 1 0 3
  6. 0

【Sample Output】

  1. 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作为边权。

  1. /* ***********************************************
  2. MYID : Chen Fan
  3. LANG : G++
  4. PROG : PKU_2728
  5. ************************************************ */
  6.  
  7. #include <iostream>
  8. #include <cstdio>
  9. #include <cstring>
  10. #include <algorithm>
  11. #include <cmath>
  12. #include <queue>
  13. #include <bitset>
  14.  
  15. using namespace std;
  16.  
  17. typedef struct nod
  18. {
  19. int x,y,z;
  20. } node;
  21. node p[];
  22.  
  23. double getdist(int i,int j)
  24. {
  25. 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));
  26. }
  27.  
  28. typedef struct enod
  29. {
  30. int x,y;
  31. double dist,cost,r;
  32. friend bool operator < (enod a,enod b)
  33. {
  34. return a.r>b.r;
  35. }
  36. } enode;
  37.  
  38. enode gete(int x,int y,double dist,double cost,double l)
  39. {
  40. enode a;
  41. a.x=x;a.y=y;a.dist=dist;a.cost=cost;
  42. a.r=cost-l*dist;
  43. return a;
  44. }
  45.  
  46. double prim(int n,double l)
  47. {
  48. priority_queue<enode> q;
  49. while (!q.empty()) q.pop();
  50. bitset<> flag;
  51. flag.reset();
  52. flag[]=;
  53. double cost=,dist=;
  54. for (int i=;i<=n;i++) q.push(gete(,i,getdist(,i),abs(p[].z-p[i].z),l));
  55.  
  56. for (int i=;i<n;i++)
  57. {
  58. enode now=q.top();
  59. q.pop();
  60. while (flag[now.y])
  61. {
  62. now=q.top();
  63. q.pop();
  64. }
  65. flag[now.y]=;
  66. cost+=now.cost;dist+=now.dist;
  67. for (int j=;j<=n;j++)
  68. if (j!=now.y&&!flag[j])
  69. q.push(gete(now.y,j,getdist(now.y,j),abs(p[now.y].z-p[j].z),l));
  70. }
  71.  
  72. return cost/dist;
  73. }
  74.  
  75. int main()
  76. {
  77. freopen("2728.txt","r",stdin);
  78.  
  79. int n;
  80. while (scanf("%d",&n))
  81. {
  82. if (n==) break;
  83.  
  84. for (int i=;i<=n;i++) scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
  85.  
  86. double l=,ans;
  87. while ()
  88. {
  89. ans=prim(n,l);
  90. if (fabs(ans-l)<1e-) break;
  91. else l=ans;
  92. }
  93.  
  94. printf("%.3f\n",ans);
  95. }
  96.  
  97. return ;
  98. }

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. linux压缩和解压缩命令

    压缩:tar -zcvf 名称.tar.gz 文件夹 解压:tar -zxvf 包名.tar.gz 解压路径

  2. springMVC中ajax的运用于注意事项

    ajax的运用: 注意事项: dataType:"json"在ajax中可写可不写(ajax能够自动识别返回值类型),写了更加规范,可以在ajax识别错误返回值类型的时候,指定返回 ...

  3. 1.2 Python基本语法

    1.交互模式编程 cmd窗口   =>输入 Python => 输入 print "hello,python!";        ps:如果是新版本Python,需要输 ...

  4. Redis 笔记

    Redis是一个key-value存储系统.和Memcached类似,但是解决了断电后数据完全丢失的情况,而且她支持更多无化的value类型,除了和string外,还支持lists(链表).sets( ...

  5. TextureView+SurfaceTexture+OpenGL ES来播放视频(二)

    引自:http://www.jianshu.com/p/b2d949ab1a1a 在使用OpenGL ES 绘制前,我先概括下接下来要做的工作:我先借用一个博主kiffa举的的一个栗子,我觉得说的恰到 ...

  6. Number Sequence HDU 1711 KMP 模板

    题目大意:两个数组匹配,求子串首次出现的位置. 题目思路:数组长度,比较大,朴素算法的时间复杂度为 m*n超时.KMP的时间复杂度为m+n可行. #include<iostream> #i ...

  7. GUI矩形、椭圆、线、框架

    所有的Swing组件必须由时间调度线程(event dispatch thread)进行配置,线程将鼠标点击和键盘敲击控制转移到用户接口组件.下面的代码片段是事件调度线程中的执行代码: EventQu ...

  8. Java中域 实例域 静态域

    1.java中的域 所谓的域,翻译成英文就是field, 也就是我们常说的字段,或者说是属性. 比如类的字段(属性),局部的,全局的.所谓域,其实是“field”的翻译 然后实例域,就是 实例(&qu ...

  9. 2016中国大学生程序设计竞赛 - 网络选拔赛 1001 A water problem (大数取余)

    Problem Descripton Two planets named Haha and Xixi in the universe and they were created with the un ...

  10. MaterialEditText 控件学习

    这个视图原始框架地址:https://github.com/rengwuxian/MaterialEditText 指导手册:http://www.rengwuxian.com/post/materi ...