最小比率树 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的割.对于带权图来说,将 所有顶点处在 ...
随机推荐
- CSS样式2
1.css重用 <style> .cl{ ... } .c2{ ... } .c{ ... } </style> <div class='c c2'></di ...
- 项目Alpha冲刺 Day12
1)站立式会议: 2)今日安排: 项目演示. 3)项目情况 项目进展:系统已实现预期的所有的功能.问题困难:系统测试不够全面,主要做功能测试,对于非功能测试,如压力测试.效能测试.安全性等并未测试.心 ...
- 图论--DFS总结
1.Key word:①双向DFS ②回溯 今天就看到了这么多DFS,其实DFS更倾向于枚举所有情况. 对于双向DFS,我们考虑看看最短路,起点做一下搜索,记录一下到所有点的距离,终点做一下搜索,记 ...
- 一个简单的wed服务器SHTTPD(6)———— SHTTPD错误处理的实现
//start from the very beginning,and to create greatness //@author: Chuangwei Lin //@E-mail:979951191 ...
- 多源最短路径算法:Floyd算法
前言 由于本人太菜,这里不讨论Floyd的正确性. 简介 多源最短路径,解决的是求从图中任意两点之间的最短路径的问题. 分析 代码短小精悍,主要代码只有四行,直接放上: for(int k=1;k&l ...
- 支付宝小程序云开发serverless----获取用户的user_id
支付宝小程序云开发serverless----获取用户的user_id 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 开通云调 ...
- SecureCRT怎么将本级文件上传到CentOS
进入到想要放文件的路径,不然会默认放在当前路径下: 输入 rz -------------------------------------------------------------------- ...
- 博客第一天:Typora和Markown语法初始
------------恢复内容开始------------ Markdown学习 一级标题:#+空格 二级标题:##+空格 三级标题:###+空格 四级标题:####+空格 五级标题:#####+空 ...
- 简单谈谈Spring的IoC
一.前言 这几天正在复习Spring的相关内容,同时想要对Spring的实现原理做一些深入的研究.今天看了看Spring中IoC的实现,找到了一篇非常详细的博客,研究了一个下午,看完之后唯一的感受 ...
- Linux系统上LNMP服务器的搭建
一.确保登录用户权限为root 如果没有root权限: su root 切换到root用户,但不切换环境变量: 或者 su - root 完整地切换到root用户环境. 二.开始下载并安装LNMP( ...