最小比率树 poj2728
以下内容均为转载
http://www.cnblogs.com/ftae/p/6947497.html
poj2728
题意
给出 n 个点的坐标和它的高度,求一颗生成树使得树上所连边的两点高度差之和除以距离之和最小。
分析
01分数规划+最小生成树。
对于所有的边,在求最小生成树过程中有选或不选的问题,
首先根据01分数规划,我们要使 











































l=∑i=1nheight[i]∗exist[i]∑i=1ndis[i]∗exist[i]
(exist[i]表示是否有这条边)最小,
设 









































F(l)=∑height[i]∗exist[i]−l∗∑dis[i]∗exist[i]
,我们要使
l
尽可能的小, 


F(l)
随
l
减小而递增,如果 




F(l)<0
,











































∑i=1nheight[i]∗exist[i]∑i=1ndis[i]∗exist[i]<l
,即存在更优的
l
,当 




F(l)=0
时,即为最终最终答案
l
。
设 





















D(l)=height[i]−dis[i]∗l
,把它作为边,求最小生成树,那么求得值 


F(l)
一定是尽可能小的,越有可能出现更优的
l
。
本题适于采用迭代法,因为在求最小生成树的过程中,就可以计算出更优的
l
值。
code(二分法)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e3 + 10;
const double INF = 1e15;
int n;
double dist(double x1, double y1, double x2, double y2) {
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
struct node {
double x, y, h;
}a[MAXN];
double height[MAXN][MAXN];
double map[MAXN][MAXN];
double dis[MAXN];
int vis[MAXN];
double prime(double rate) {
double sum = 0;
memset(vis, 0, sizeof vis);
for(int i = 1; i <= n; i++) {
dis[i] = INF;
}
dis[1] = 0;
for(int i = 0; i < n; i++) {
double MIN = INF;
int k;
for(int j = 1; j <= n; j++) {
if(!vis[j] && dis[j] < MIN) MIN = dis[k = j];
}
vis[k] = 1;
sum += MIN;
for(int j = 1; j <= n; j++) {
if(!vis[j] && dis[j] > height[k][j] - rate * map[k][j]) {
dis[j] = height[k][j] - rate * map[k][j];
}
}
}
return sum;
}
void solve() {
double l = 0, r = 1e5, mid = 0;
while(r - l > 1e-6) {
mid = (l + r) / 2;
if(prime(mid) < 0) r = mid;
else l = mid;
}
printf("%.3f\n", mid);
}
int main() {
while(cin >> n && n) {
for(int i = 1; i <= n; i++) {
cin >> a[i].x >> a[i].y >> a[i].h;
for(int j = 1; j <= i; j++) {
map[i][j] = map[j][i] = dist(a[i].x, a[i].y, a[j].x, a[j].y);
height[i][j] = height[j][i] = abs(a[i].h - a[j].h);
}
}
solve();
}
return 0;
}
code(迭代法)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e3 + 10;
const double INF = 1e15;
int n;
double dist(double x1, double y1, double x2, double y2) {
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
struct node {
double x, y, h;
}a[MAXN];
double height[MAXN][MAXN];
double map[MAXN][MAXN];
double dis[MAXN];
int vis[MAXN], pre[MAXN];
double prime(double rate) {
double sum = 0;
double sumh = 0, sumd = 0;
memset(vis, 0, sizeof vis);
for(int i = 1; i <= n; i++) {
dis[i] = INF;
pre[i] = 0;
}
dis[1] = 0;
for(int i = 0; i < n; i++) {
double MIN = INF;
int k;
for(int j = 1; j <= n; j++) {
if(!vis[j] && dis[j] < MIN) {
MIN = dis[k = j];
}
}
vis[k] = 1;
sum += MIN;
sumd += map[pre[k]][k];
sumh += height[pre[k]][k];
for(int j = 1; j <= n; j++) {
if(!vis[j] && dis[j] > height[k][j] - rate * map[k][j]) {
dis[j] = height[k][j] - rate * map[k][j];
pre[j] = k;
}
}
}
return sumh / sumd;
}
void solve() {
double k = 0, tmp;
while(1) {
tmp = prime(k);
if(fabs(tmp - k) < 1e-6) break;
else k = tmp;
}
printf("%.3f\n", k);
}
int main() {
while(cin >> n && n) {
for(int i = 1; i <= n; i++) {
cin >> a[i].x >> a[i].y >> a[i].h;
for(int j = 1; j <= i; j++) {
map[i][j] = map[j][i] = dist(a[i].x, a[i].y, a[j].x, a[j].y);
height[i][j] = height[j][i] = abs(a[i].h - a[j].h);
}
}
solve();
}
return 0;
}
最小比率树 poj2728的更多相关文章
- [LeetCode] Minimum Height Trees 最小高度树
For a undirected graph with tree characteristics, we can choose any node as the root. The result gra ...
- [BZOJ3754]Tree之最小方差树
3754: Tree之最小方差树 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 402 Solved: 152[Submit][Status][Di ...
- 【BZOJ-4435】Juice Junctions 最小割树(分治+最小割)+Hash
4435: [Cerc2015]Juice Junctions Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 20 Solved: 11[Submi ...
- 【BZOJ-2229】最小割 最小割树(最大流+分治)
2229: [Zjoi2011]最小割 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1565 Solved: 560[Submit][Status ...
- [swustoj 404] 最小代价树
最小代价树(0404) 问题描述 以下方法称为最小代价的字母树:给定一正整数序列,例如:4,1,2,3,在不改变数的位置的条件下把它们相加,并且用括号来标记每一次加法所得到的和. 例如:((4+1)+ ...
- 【UVA 10816】 Travel in Desert (最小瓶颈树+最短路)
[题意] 有n个绿洲, m条道路,每条路上有一个温度,和一个路程长度,从绿洲s到绿洲t,求一条道路的最高温度尽量小, 如果有多条, 选一条总路程最短的. InputInput consists of ...
- [洛谷]P3729 曼哈顿计划EX(最小割树/等价流树)
题目大意:给出一张n个点m条边的无向图,每个点有点权,q次询问,每次给出k,要求选出若干个点点权之和不小于k,求一个最大的值x,使得选出的点中任意两点之间至少有x条互不相交的链.(n<=550, ...
- [Swift]LeetCode310. 最小高度树 | Minimum Height Trees
For an undirected graph with tree characteristics, we can choose any node as the root. The result gr ...
- BZOJ4519[Cqoi2016]不同的最小割——最小割树+map
题目描述 学过图论的同学都知道最小割的概念:对于一个图,某个对图中结点的划分将图中所有结点分成 两个部分,如果结点s,t不在同一个部分中,则称这个划分是关于s,t的割.对于带权图来说,将 所有顶点处在 ...
随机推荐
- Linux 用户管理和提权
Linux ⽀持多个⼈使⽤同⼀个⽤户登录系统, Windows 在修改组策略的情况下,也可以多个⼈使⽤同⼀个⽤户登录 远程连接Linux的⽅式:SSH协议 远程连接Windows的⽅式:RDP协议 安 ...
- MySQL数据库的套接字文件和pid文件
MySQL数据库的套接字文件和pid文件 socket文件:当用Unix域套接字方式进行连接时需要的文件. pid文件:MySQL实例的进程ID文件. MySQL表结构文件:用来存放MySQL表结构定 ...
- 【批处理】TXT文件批量转HTML文件工具
说到批量转html文件,相信喜欢看小说或经常制作电子书和教程的朋友应该很熟悉.因为,我们每次都会面临成千上万的txt文件,要将其转换为能正确显示的html文件是很麻烦的.当然,现在有很多的软件也可以实 ...
- 前端程序员难翻身,没有好的学习方法,你永远无法成功,vue.js专题
学习vue正确思路,是先学vue-cli,再学vue.js单文件引用的用法,这样会在极短时间内撤底撑握vue, 如果先学vue.js单文件用法,再去学vue-cli4,可以说是重新学vue,,,,难处 ...
- AWVS 安全渗透扫描
1.打开软件,点击 New Scan 2.在 website url 中输入被扫描的网址,点击 next 3.在 scanning profile 中选择测试的漏洞类型,默认选择 default(默认 ...
- dos命令下安装pip报错 不是内部命令
在dos命令下: pip install requests 遇到这种情况一般是Python的环境变量没有设置好 解决方案一:设置环境变量 C:\Python\scripts 如图 是否有pytho ...
- LeetCode 98. 验证二叉搜索树 | Python
98. 验证二叉搜索树 题目来源:https://leetcode-cn.com/problems/validate-binary-search-tree 题目 给定一个二叉树,判断其是否是一个有效的 ...
- HTTP请求头中的X-Forwarded-For介绍
概述 我们在做nginx方向代理的时候,为了记录整个代理过程,我们往往会在配置文件中加上如下配置: location ^~ /app/download/ { ... proxy_set_header ...
- 模块(类)之间解耦利器:EventPublishSubscribeUtils 事件发布订阅工具类
如果熟悉C#语言的小伙伴们一般都会知道委托.事件的好处,只需在某个类中提前定义好公开的委托或事件(委托的特殊表现形式)变量,然后在其它类中就可以很随意的订阅该委托或事件,当委托或事件被触发执行时,会自 ...
- Flutter 1.17版本重磅发布
Flutter 1.17 是2020年的第一个稳定版本,此版本包括iOS平台Metal支持(性能更快),新的Material组件,新的Network跟踪工具等等! 对所有人来说,今年是充满挑战的一年. ...