用01分数规划 + prime + 二分 竟然2950MS惊险的过了QAQ

前提是在TLE了好几次下过的 = =

题目意思:
有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可,建造水管距离为坐标之间的欧几里德距离,费用为海拔之差,现在要求方案使得费用与距离的比值最小,很显然,这个题目是要求一棵最优比率生成树。

解题思路:

对答案进行二分,当把代进去的答案拿来算最小生成树的时候,一旦总路径长度为0,就是需要的答案。

0-1规划是啥?
 
概念
有带权图G, 对于图中每条边e[i], 都有benifit[i](收入)和cost[i](花费), 我们要求的是一棵生成树T, 它使得 ∑(benifit[i]) / ∑(cost[i]), i∈T 最大(或最小).这显然是一个具有现实意义的问题.
解法之一 0-1分数规划
设x[i]等于1或0, 表示边e[i]是否属于生成树.
则我们所求的比率 r = ∑(benifit[i] * x[i]) / ∑(cost[i] * x[i]), 0≤i<m .
为了使 r 最大, 设计一个子问题---> 让 z = ∑(benifit[i] * x[i]) - l * ∑(cost[i] * x[i]) = ∑(d[i] * x[i]) 最大 (d[i] = benifit[i] - l * cost[i]) , 并记为z(l). 我们可以兴高采烈地把z(l)看做以d为边权的最大生成树的总权值.

然后明确两个性质:
 1. z单调递减
  证明: 因为cost为正数, 所以z随l的减小而增大.
 2. z( max(r) ) = 0
  证明: 若z( max(r) ) < 0, ∑(benifit[i] * x[i]) - max(r) * ∑(cost[i] * x[i]) < 0, 可化为 max(r) < max(r). 矛盾;
   若z( max(r) ) >= 0, 根据性质1, 当z = 0 时r最大.

贴代码:

 //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler
#include <stdio.h>
#include <iostream>
#include <climits>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <algorithm>
#define ll long long
using namespace std; const int INF = 0x3f3f3f3f;
const int MAXN = ;
struct node{
double x,y,h;
}dot[MAXN]; double map[MAXN][MAXN];
int n;
double dis(double x1,double y1,double x2,double y2){
return sqrt( (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1) );
} void creat(int n,double l){
for(int i=;i<=n;i++) for(int j=;j<=n;j++)
map[i][j]=fabs(dot[i].h-dot[j].h) - l * dis(dot[i].x,dot[i].y,dot[j].x,dot[j].y);
} double prim(){
bool vis[MAXN];
memset(vis, , sizeof(vis));
double dis[MAXN];
double ans = ;
int i,j;
vis[] = true;
for(i = ; i <= n; ++i)
dis[i] = map[][i];
for(i = ; i < n; ++i){
int temp = INF, flag;
for(j = ; j <= n; ++j){
if(!vis[j] && dis[j] <= temp){
temp = dis[j];
flag = j;
}
}
vis[flag] = true;
ans += dis[flag];
for(j = ; j <= n; ++j){
if(!vis[j] && map[flag][j] < dis[j])
dis[j] = map[flag][j];
}
}
return ans;
} int main(){
int i,j;
double res,front,rear, mid;
while(EOF != scanf("%d",&n)){
if(n==) break;
for(i=;i<=n;i++)
scanf("%lf%lf%lf",&dot[i].x,&dot[i].y,&dot[i].h);
front = ;
rear = 100.0;//doubt
while(front <= rear){
mid = (front + rear) / ;
creat(n,mid);
res = prim();
if(fabs(res) < 1e-)
break;
else if(res > 1e-)
front = mid;
else
rear = mid;
}
printf("%.3f\n",mid);
}
return ;
}

POJ2728 最小比率生成树/0-1分数规划/二分/迭代(迭代不会)的更多相关文章

  1. POJ.2728.Desert King(最优比率生成树 Prim 01分数规划 二分/Dinkelbach迭代)

    题目链接 \(Description\) 将n个村庄连成一棵树,村之间的距离为两村的欧几里得距离,村之间的花费为海拔z的差,求花费和与长度和的最小比值 \(Solution\) 二分,假设mid为可行 ...

  2. Bzoj1486/洛谷P3199 最小圈(0/1分数规划+spfa)/(动态规划+结论)

    题面 Bzoj 洛谷 题解(0/1分数规划+spfa) 考虑\(0/1\)分数规划,设当前枚举到的答案为\(ans\) 则我们要使(其中\(\forall b_i=1\)) \[ \frac{\sum ...

  3. poj2728 最小比率生成树——01分数规划

    题目大意: 有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水, 只要两个村庄之间有一条路即可,建造水管距离为坐标之间的欧几里德距离,费用为海拔之差, 现在要求方案使得费用与距离的比值最小,很显然 ...

  4. POJ 2728 Desert King(最优比率生成树, 01分数规划)

    题意: 给定n个村子的坐标(x,y)和高度z, 求出修n-1条路连通所有村子, 并且让 修路花费/修路长度 最少的值 两个村子修一条路, 修路花费 = abs(高度差), 修路长度 = 欧氏距离 分析 ...

  5. poj2728 Desert King【最优比率生成树】【Prim】【0/1分数规划】

    含[最小生成树Prim]模板. Prim复杂度为$O(n^2),适用于稠密图,特别是完全图的最小生成树的求解.   Desert King Time Limit: 3000MS   Memory Li ...

  6. POJ2728 Desert King (最小生成树、0/1分数规划)

    显然的0/1分数规划问题,用二分来解决,检验mid,就用prim算法求最小生成树,看总边权是否大等于0即可验证. 1 #include<bits/stdc++.h> 2 using nam ...

  7. poj 2976 Dropping tests 0/1分数规划

    0/1分数规划问题,用二分解决!! 代码如下: #include<iostream> #include<stdio.h> #include<algorithm> # ...

  8. bzoj 3597: [Scoi2014]方伯伯运椰子 0/1分数规划

    3597: [Scoi2014]方伯伯运椰子 Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 144  Solved: 78[Submit][Status ...

  9. LOJ 3089 「BJOI2019」奥术神杖——AC自动机DP+0/1分数规划

    题目:https://loj.ac/problem/3089 没想到把根号之类的求对数变成算数平均值.写了个只能得15分的暴力. #include<cstdio> #include< ...

随机推荐

  1. python re(正则模块)

    参考文档:http://blog.csdn.net/wusuopubupt/article/details/29379367 ipython环境中,输入"?re",官方解释如下: ...

  2. selenium 学习笔记 ---新手学习记录(10) 问题总结(java)--poi--excel 操作

    1.当我使用poi想要操作xlsx时,报错,解决方法下载xmlbeans-2.6.0.jar架包,引入即可.点我下载 https://yunpan.cn/cSdVqp6e4v6Jk  访问密码 2c5 ...

  3. IOS 学习笔记(5) 控件 文本视图(UITextView)的使用方法

    相对于UILabell所支持的较短文本内容,UITextView对于长文本的支持更好.UITextView能够以滚动的方式全部浏览到长文本,并且就像UILabel那样,从ISO6,他也提供了对NSAt ...

  4. Hibernate 知识提高

    主键生成策略有: UUID,increment.Hilo.assigned:对数据库无依赖 identity:依赖Mysql或sql server,主键值不由hibernate维护 sequence: ...

  5. Qt 4.6: A Quick Start to Qt Designer

    Qt 4.6: A Quick Start to Qt Designer A Quick Start to Qt Designer Using Qt Designer involves four ba ...

  6. .net c# 提交包含文件file 的form表单 获得文件的Stream流

    1.前台html代码 要写一个有id的form,可是不能有runat="server"属性.由于一个页面中,有这个属性的form表单仅仅能有一个. 再要有一个有name的ifram ...

  7. 都div在所有li的html()值被设置&quot;哈哈&quot;,当点击设置&quot;我被点击&quot;,其余的还是不点击设置“哈哈”

    <1> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://w ...

  8. js中this的深入研究

    this对象是函数在运行时由调用函数的对象决定的: 1.在全局对象中运行函数时,this等于window 2.当函数被作为某个对象的方法调用时, this等于那个对象. 需要注意的几点: 声明函数里的 ...

  9. C# 读取Excel日期格式

    读取Excel日期数据,一种方式是在EXCEL中把你的日期列的格式设置一下,设成"文本"型. 如果单元格格式设置为date,则在后台读出的数值是一个数值,如2008-08-08读出 ...

  10. 【Linux命令】杀死僵尸程序

    A zombie is already dead, so you cannot kill it. To clean up a zombie, it must be waited on by its p ...