POJ 2728 Desert King(最优比例生成树)
来源:互联网 发布:广州seo外包eiaike 编辑:程序博客网 时间:2024/05/15 17:21
题目大意
有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可,建造水管距离为坐标之间的欧几里德距离,费用为海拔之差,现在要求方案使得费用与距离的比值最小,很显然,这个题目是要求一棵最优比率生成树。
解法
有带权图G, 对于图中每条边e[i], 都有benefiti和costi, 我们要求的是一棵生成树T, 它使得 ∑(benefit[i]) / ∑(cost[i]), i∈T 最大(或最小).
设x[i]等于1或0, 表示边e[i]是否属于生成树.
则我们所求的比率 r = ∑(benefit[i] * x[i]) / ∑(cost[i] * x[i]), 0≤ i < m .
为了使 r 最大, 设计一个子问题—> 让 z = ∑(benefit[i] * x[i]) - l * ∑(cost[i] * x[i]) = ∑(d[i] * x[i]) 最大 (d[i] = benefit[i] - l * cost[i]) , 并记为z(l). 我们可以兴高采烈地把z(l)看做以d为边权的最大生成树的总权值.
然后明确两个性质:
1. z单调递减
证明: 因为cost为正数, 所以z随l的减小而增大.
2. z( max(r) ) = 0
证明: 若z( max(r) ) < 0, ∑(benefit[i] * x[i]) - max(r) * ∑(cost[i] * x[i]) < 0, 可化为 max(r) < max(r). 矛盾;
若z( max(r) ) >= 0, 根据性质1, 当z = 0 时r最大.
转自zhang20072844
但是上面讲得很清楚了,但是我依然理解了很久,首先我说明本题为什么找的是最小生成树。假设∑(benefit[i])/∑(cost[i])=min,我们知道d[i]是每条边的边权,假如说存在一个更优的d[j]使∑(benefit[i])/∑(cost[i])< min,很明显d[j]要小于d[i],于是本题很明显应该找最小生成树才能找到最小的比例。
#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>const int maxn = 1005;const double inf = 0x3f3f3f3f;const double eps = 1e-5;int vis[maxn],x[maxn],y[maxn],z[maxn],pre[maxn];double dis[maxn],cost[maxn][maxn],dist[maxn][maxn];int n;double prim(double rate){ double sum = 0.0; for (int i = 1; i <= n; i++) pre[i] = 1, dis[i] = inf; dis[1] = 0; memset(vis, 0, sizeof(vis)); for (int i = 1; i <= n; i++){ double Min = inf; int tmp; for (int j = 1; j <= n; j++) if (!vis[j] && dis[j] < Min) Min = dis[tmp = j]; vis[tmp] = 1; sum += Min; for (int j = 1; j <= n; j++) if (dis[j] > cost[tmp][j] - dist[tmp][j]*rate){ dis[j] = cost[tmp][j] - dist[tmp][j]*rate; pre[j] = tmp; } } return sum;}int main(){ while(scanf("%d", &n) && n){ for(int i = 1; i <= n; i++){ scanf("%d%d%d", &x[i], &y[i], &z[i]); for (int j = 1; j < i; ++j){ double tmp = (x[i] - x[j])*(x[i] - x[j]) + (y[i] - y[j])*(y[i] - y[j]); cost[i][j] = cost[j][i] = abs(z[i] - z[j]); dist[i][j] = dist[j][i] = sqrt(tmp); } } double l = 0,r = 1000000.0; while (r - l > eps){ double mid = (l + r)/2.0; if (prim(mid) >= 0) l = mid; else r = mid; } printf("%.3f\n", r); } return 0;}
- poj 2728 Desert King(最优比例生成树)
- POJ 2728 Desert King(最优比例生成树)
- poj 2728 Desert King(最优比例生成树)
- poj 2728 Desert King(最优比例生成树)
- poj 2728 Desert King(最优比例生成树)
- poj 2728 Desert King(最优比例生成树)
- POJ 2728 Desert King 最优比例生成树
- POJ 2728 Desert King 最优比例生成树
- POJ 2728 Desert King(最优比例生成树)
- POJ 2728 Desert King (最优比例生成树)
- POJ 2728 Desert King (最优比例生成树)
- POJ 2728 Desert King (最优比例生成树)
- POJ 2728 Desert King (最优比例生成树)
- POJ 2728 Desert King (最优比例生成树)
- poj Desert King 最优比例生成树 01分数规划
- poj2728 Desert King,最优比例生成树
- POJ2728 Desert King 最优比例生成树
- poj 2728(Desert King) 最优比例生成树 (分数规划)
- java.lang.reflect.Type
- 将博客搬至CSDN
- Git教程学习(四)—版本控制
- 树梅派应用52:让树莓派自动上报IP地址到邮箱
- java ME、java SE和java EE的区别
- POJ 2728 Desert King(最优比例生成树)
- C++和QML混合编程
- 三分钟教你学Git(二十二) - 互动式改写历史
- day05--js数据类型
- PHP-redis中文文档
- NAPI 技术在 Linux 网络驱动上的应用和完善
- iOS多线程 -----------NSThread
- android 状态栏、标题栏、屏幕高度 设置全屏的方法
- # json的处理 #