题面:[USACO 2001 OPEN]地震

题目描述:

一场地震把约翰家的牧场摧毁了, 坚强的约翰决心重建家园。 约翰已经重建了N个牧场,现在他希望能修建一些道路把它们连接起来。研究地形之后,约翰发现可供修建的道路有M条。碰巧的是,奶牛们最近也成立一个工程队,专门从事修复道路。而然,奶牛们很有经济头脑,如果无利可图,它们是不会干的。

奶牛们关注的是挣钱速度,即总利润和总施工时间的比值。约翰和奶牛达成了协议,奶牛负责修建道路,将所有牧场连通,而约翰需要支付F元。每条道路都有自己的施工时间和建造成本。连接两个相同的牧场的道路可能有多条。保证所有的牧场必定是可连通的,不过也有可能一些道路的建造成本之和会超过F。

请帮助奶牛们选择修复哪些道路,才能使单位时间的利润最大?

输入格式:

第一行:三个整数: N,M和F, $ 1 ≤ N ≤ 400 $ , $ 1 ≤ M ≤ 10000 $ , $ 1 ≤ F ≤ 2 × 10^9 $

第二行到 $ M + 1 $ 行:第 $ i + 1 $ 行表示第i条道路的信息,有四个整数: $ U_i $ , $ V_i $ , $ C_i $ 和 $ T_i $ , $ U_i $ 和 $ V_i $ 表示这条道路连接的牧场编号,Ci表示道路修建的成本,Ti表示道路修建所需要的时间, $ 1 ≤ U_i ≤ N $ , $ 1 ≤ V_i ≤ N $ , $ 1 ≤ C_i ≤ 2 × 10^9 $ , $ 1 ≤ T_i ≤ 2 × 10^9 $

输出格式:

第一行:一个保留四位小数的浮点数,表示奶牛们能挣到的最大单位时间利润,如果奶牛们无钱可赚,则输出0.0000

输入样例#1:

5 5 100

1 2 20 5

1 3 20 5

1 4 20 5

1 5 20 5

2 3 23 1

输出样例#1:

1.0625

说明:

(奶牛们可以选择连通最后四条道路,则总时间为 16,总成本为 83,所以单位利润为17/16 = 1.0625)

$ solution: $

这题其实牵扯到了一种普遍的二分答案的方法,与我等下会讲的HNOI2009 最小圈 一样有许多的共同点。因为这些题要求我们输出的ans都是针对权值总和不断计算而来的。本题就是个经典例题(二分答案求最优比率生成树),因为我们可以直接通过题意看出它要求我们输出的最终答案实际上就是:

$ ans= \frac{F-\sum{v_i} \quad (i\in S)}{\sum{t_i}\quad (i\in S)} $

(其中S为我们最终所选择的最优生成树的边权的集合)我们将这个式子转换一下,可以得到:

$ F=ans\times \sum{t_i}+\sum{v_i} $

$ F=\sum{ans\times t_i+v_i}\quad _{(i\in S)} $

注:这一点我们一定要清楚:此时等式右边就是生成树(只不过;树边权变成了 $ ans\times t_i+v_i $ )

上述式子中我们的ans就是我们最终要输出的最优比率,这个ans是我们可以二分得到的!因为答案具有单调性,当然这个需要我们进一步证明:首先,因为ans是最优比率,那么我们可以知道,对于图上的任意一个生成树的边的集合K,一定有: $ \frac{F-\sum{v_i} \quad (i\in K)}{\sum{t_i}\quad (i\in K)}\leq ans $ (根据上述方式转化得: $ F\leq \sum{ans\times t_i+v_i}\quad {(i\in K)} $ )只有当我们的集合K取到最优的生成树时也就是K=S的时候,这个式子才会是等式!然后我们来证明二分的正确性:当我们二分求ans的时候,对于我们当前的比率x,一定有这三种情况:

$ 1. $ $ x>ans $ :

当我们比率为ans时: $ F\leq \sum{ans\times t_i+v_i}\quad {(i\in K )} $

现在我们的比率x比ans还大!那我们的肯定有: $ F< \sum{x\times t_i+v_i}\quad {(i\in K)} $

$ 2. $ $ x=ans $ :

我已经说过了: $ F\leq\sum{ans\times t_i+v_i}\quad {(i\in K)} $

$ 3. $ $ x<ans $ :

这个时候我们发现我们不能确认 $ F $ 和 $ \sum{ans\times t_i+v_i}\quad {(i\in K)} $ 的大小关系了!因为我们的K是任意生成树的边的集合,此时我们小于等于大于都有可能,但也正是如此,我们可以证明一定存在一个边的集合满足 $ F>\sum{x\times t_i+v_i}\quad {(i\in S)} $ 因为就拿我们ans情况下的最优边集S,因为 $ F=\sum{ans\times t_i+v_i}\quad {(i\in S)} $ 此时我们的 $ x<ans $ 所以 $ F>\sum{x\times t_i+v_i}\quad {(i\in S)} $

如何二分(为什么用最小生成树):

那我们证明了上面这个东西有什么用呢?根据上述三个关系的特性(就是那三个不等式),我们发现当我们将x带进去后,只要求得最小的 $ \sum{ans\times t_i+v_i}\quad {(i\in K)} $ 我们就可以直接判断出x和ans的关系了!

我们将最小的 $ \sum{ans\times t_i+v_i}\quad {(i\in K)} $ 看做min

  1. 若 $ F<min $ ,则必有 $ F< \sum{x\times t_i+v_i}\quad {(i\in K)} $ 这不就是第一种情况吗?x必然大于ans

  2. 若 $ F=min $ ,则必有 $ F \leq \sum{x\times t_i+v_i}\quad {(i\in K)} $ 这不就是第一种情况吗?x必然等于ans

  3. 若 $ F>min $ ,则x必然不大于也不等于ans,那不就是小于ans吗?(证过了若x<ans,则必存在一个K $ F>\sum{x\times t_i+v_i}\quad {(i\in K)} $ )

那我们如何求最小的 $ \sum{x\times t_i+v_i}\quad {(i\in K)} $ 呢? 这就是求最小生成树嘛(只不过;树边权变成了 $ ans\times t_i+v_i $ ,我们每一次都重新排个序就行了)!

总复杂度: $ O(m \times logm\times log(r-l+1)) $

$ code: $

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set> #define ll long long
#define db double
#define rg register int using namespace std; const db cha=1e-9; struct su{
int x,y,v,t;db k;
}a[10005]; int n,m,f;
int s[405]; inline int qr(){
char ch;
while((ch=getchar())<'0'||ch>'9');
int res=ch^48;
while((ch=getchar())>='0'&&ch<='9')
res=res*10+(ch^48);
return res;
} inline bool cmp(su x,su y){return x.k<y.k;} inline int get(int x){
if(s[x]==x)return x;
return s[x]=get(s[x]);
} inline bool check(db x){
db res=0;
for(rg i=1;i<=n;++i)s[i]=i;//并查集
for(rg i=1;i<=m;++i)
a[i].k=x*a[i].t+(db)a[i].v;//更新边权
sort(a+1,a+m+1,cmp);//kruskal求最小生成树
for(rg i=1;i<=m;++i)
if(get(a[i].x)!=get(a[i].y))
res+=a[i].k,s[get(a[i].x)]=get(a[i].y);//求新边权的总和
return f>res?0:1;
} int main(){
freopen("quake.in","r",stdin);
freopen("quake.out","w",stdout);
n=qr(),m=qr(),f=qr();
for(rg i=1;i<=m;++i)
a[i]=su{qr(),qr(),qr(),qr()};
if(check(0))puts("0.0000"),exit(0);//特判
db l=0,r=1e14,mid;
while(r-l>cha){//二分答案
mid=(l+r)/2;
if(check(mid))r=mid-cha;
else l=mid+cha;
}printf("%.4lf",l);
return 0;
}

[USACO]地震 (二分答案+最优比率生成树详解)的更多相关文章

  1. [转]01分数规划算法 ACM 二分 Dinkelbach 最优比率生成树 最优比率环

    01分数规划 前置技能 二分思想最短路算法一些数学脑细胞? 问题模型1 基本01分数规划问题 给定nn个二元组(valuei,costi)(valuei,costi),valueivaluei是选择此 ...

  2. POJ 2728 Desert King ★(01分数规划介绍 && 应用の最优比率生成树)

    [题意]每条路径有一个 cost 和 dist,求图中 sigma(cost) / sigma(dist) 最小的生成树. 标准的最优比率生成树,楼教主当年开场随手1YES然后把别人带错方向的题Orz ...

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

    http://poj.org/problem?id=2728 题意: 在这么一个图中求一棵生成树,这棵树的单位长度的花费最小是多少? 思路: 最优比率生成树,也就是01分数规划,二分答案即可,题目很简 ...

  4. 2018.09.12 earthquake(最优比率生成树)

    描述 地震已经破坏了农夫约翰所有的农场以及所有连接农场的道路.作为一个意志坚强的人,他决定重建所有的农场.在重建全部N(1 <= N <= 400)个农场之前,首先必须把所有农场用道路连接 ...

  5. poj 2728 Desert King (最优比率生成树)

    Desert King http://poj.org/problem?id=2728 Time Limit: 3000MS   Memory Limit: 65536K       Descripti ...

  6. 最优比率生成树 poj2728

    Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 28407   Accepted: 7863 Desc ...

  7. 【最优比率生成树】poj2728 Desert King

    最优比率生成树教程见http://blog.csdn.net/sdj222555/article/details/7490797 个人觉得很明白易懂,但他写的代码略囧. 模板题,但是必须Prim,不能 ...

  8. [POJ2728] Desert King 解题报告(最优比率生成树)

    题目描述: David the Great has just become the king of a desert country. To win the respect of his people ...

  9. POJ 2728 Desert King 最优比率生成树

    Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 20978   Accepted: 5898 [Des ...

随机推荐

  1. C# 语言习惯

    目录 一.使用属性而不是可访问的数据成员 二.使用运行时常量(readonly)而不是编译时常量(const) 三.推荐使用 is 或 as 操作符而不是强制类型转换 四.使用 Conditional ...

  2. python 模块之-sys

    python 模块 sys import sys sys.argv       # 参数,第一个参数是脚本的文件明,自定义参数为数组的第二个   sys.argv[1] sys.version   # ...

  3. BZOJ2212 POI2011Tree Rotations(线段树合并)

    显然子树内的操作不会对子树外产生影响.于是贪心,若交换之后子树内逆序对减少就交换. 这个东西可以用权值线段树计算.操作完毕后需要对两棵权值线段树合并,这个的复杂度是两棵线段树的重复节点个数.那么总复杂 ...

  4. JeeSite框架中httpSession.invalidate();无效

    想要实现一个功能:同一个用户在两个不同的浏览器中登录,后面的踢掉之前的登录. 本来的思路是在httpSession监听器中进行判断.但是在使用httpSession.invalidate();销毁Se ...

  5. Shebang(#!)[转]

    原博文 使用Linux或者unix系统的同学可能都对#!这个符号并不陌生,但是你真的了解它吗? 首先,这个符号(#!)的名称,叫做"Shebang"或者"Sha-bang ...

  6. Hdoj 1009.FatMouse' Trade 题解

    Problem Description FatMouse prepared M pounds of cat food, ready to trade with the cats guarding th ...

  7. 自学Aruba1.3-WLAN厂家魔力象限

    点击返回:自学Aruba之路 自学Aruba1.3-WLAN厂家魔力象限 以下为2017<有线和无线局域网接入基础设施的魔力象限>报告:      Aruba.cisco为无线领域领导者. ...

  8. 洛谷 P2300 合并神犇 解题报告

    P2300 合并神犇 题目背景 loidc来到了NOI的赛场上,他在那里看到了好多神犇. 题目描述 神犇们现在正排成一排在刷题.每个神犇都有一个能力值p[i].loidc认为坐在附近的金牌爷能力参差不 ...

  9. luogu1345 奶牛的电信 (最小割)

    虽然割点不好搞,但是可以变成割边呀 拆点,拆出来的边权给1,原图中的边权给inf,然后跑dinic就行了 #include<bits/stdc++.h> #define pa pair&l ...

  10. luogu2827 [NOIp2016]蚯蚓 (模拟)

    可以直观地想到用优先队列来做,但数据范围是O(n)的 然后我们发现,因为我们每次挑出来的蚯蚓是单调的,所以把每个切成两段后,那两段也是对应单调的 也就是说,算上最一开始的蚯蚓,我们一共维护三个队列,三 ...