以下内容均为转载

http://www.cnblogs.com/ftae/p/6947497.html

poj2728(最小比率生成树)

 

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的更多相关文章

  1. [LeetCode] Minimum Height Trees 最小高度树

    For a undirected graph with tree characteristics, we can choose any node as the root. The result gra ...

  2. [BZOJ3754]Tree之最小方差树

    3754: Tree之最小方差树 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 402  Solved: 152[Submit][Status][Di ...

  3. 【BZOJ-4435】Juice Junctions 最小割树(分治+最小割)+Hash

    4435: [Cerc2015]Juice Junctions Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 20  Solved: 11[Submi ...

  4. 【BZOJ-2229】最小割 最小割树(最大流+分治)

    2229: [Zjoi2011]最小割 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1565  Solved: 560[Submit][Status ...

  5. [swustoj 404] 最小代价树

    最小代价树(0404) 问题描述 以下方法称为最小代价的字母树:给定一正整数序列,例如:4,1,2,3,在不改变数的位置的条件下把它们相加,并且用括号来标记每一次加法所得到的和. 例如:((4+1)+ ...

  6. 【UVA 10816】 Travel in Desert (最小瓶颈树+最短路)

    [题意] 有n个绿洲, m条道路,每条路上有一个温度,和一个路程长度,从绿洲s到绿洲t,求一条道路的最高温度尽量小, 如果有多条, 选一条总路程最短的. InputInput consists of ...

  7. [洛谷]P3729 曼哈顿计划EX(最小割树/等价流树)

    题目大意:给出一张n个点m条边的无向图,每个点有点权,q次询问,每次给出k,要求选出若干个点点权之和不小于k,求一个最大的值x,使得选出的点中任意两点之间至少有x条互不相交的链.(n<=550, ...

  8. [Swift]LeetCode310. 最小高度树 | Minimum Height Trees

    For an undirected graph with tree characteristics, we can choose any node as the root. The result gr ...

  9. BZOJ4519[Cqoi2016]不同的最小割——最小割树+map

    题目描述 学过图论的同学都知道最小割的概念:对于一个图,某个对图中结点的划分将图中所有结点分成 两个部分,如果结点s,t不在同一个部分中,则称这个划分是关于s,t的割.对于带权图来说,将 所有顶点处在 ...

随机推荐

  1. Bogon

    Definition - What does Bogon mean? A bogon is an bogus IP address from the bogon space, which is a s ...

  2. Mybatis详解系列(五)--Mybatis Generator和全注解风格的MyBatis3DynamicSql

    简介 Mybatis Generator (MBG) 是 Mybatis 官方提供的代码生成器,通过它可以在项目中自动生成简单的 CRUD 方法,甚至"无所不能"的高级条件查询(M ...

  3. 写代码?程序猿?你不能不懂的八大排序算法的Python实现

    信息获取后通常需要进行处理,处理后的信息其目的是便于人们的应用.信息处理方法有多种,通常由数据的排序,查找,插入,删除等操作.本章介绍几种简单的数据排序算法和高效的排序算法. 本章主要涉及到的知识点有 ...

  4. 一个简单的wed服务器SHTTPD(1)————命令行和文件配置解析

    开始学习<LInux网络编程>中的综合案例,虽然代码书上有,还是自己打一下加深理解和印象. 主要有两个函数,完成命令行的解析,另一个实现配置文件的解析,注释还是比较丰富的哦. //star ...

  5. django源码分析——处理请求到wsgi及视图view

    本文环境python3.5.2,django1.10.x系列 根据前上一篇runserver的博文,已经分析了本地调试服务器的大致流程,现在我们来分析一下当runserver运行起来后,django框 ...

  6. andorid jar/库源码解析之Bolts

    目录:andorid jar/库源码解析 Bolts: 作用: 用于链式执行跨线程代码,且传递数据 栗子: Task.call(new Callable<Boolean>() { @Ove ...

  7. linux进程管理相关命令

    ps ps aux ps -ef | grep -E "supervisor|PPID"  top 可以按一定规则对top的结果进行排序 # 监控单一进程 top -p pid  ...

  8. (3).mybatis编写工具类

    编写工具类 复用与重构 复用:使用方法与函数,复用的类,构成JAR包.(工具类属于复用) 一.创建工具类(一般在src下创建util包,在util包下创建工具类). 例如:MybatisUtilds为 ...

  9. LDheatmap | SNP连锁不平衡图(LD)可视化,自己数据实现版!

    本文首发于“生信补给站”,https://mp.weixin.qq.com/s/Gl6BChxSYbSHMo9oMpufPg 连锁不平衡图,用来可视化不同SNP之间的连锁程度,前同事间俗称“倒三角”图 ...

  10. 带你理解【JavaScript】中的继承机制

    前文 总所周知,继承是所有OO语言中都拥有的一个共性.在JavaScript中,它的继承机制与其他OO语言有着很大的不同,尽管ES6为我们提供了像面向对象继承一样的语法糖,但是其底层依然是构造函数,所 ...