[USACO]地震 (二分答案+最优比率生成树详解)

题面:[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*\sum{t_i}+\sum{v_i}\)

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

注:这一点我们一定要清楚:此时等式右边就是生成树(只不过;树边权变成了\(ans*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*t_i+v_i}\quad {(i\in K)}\))只有当我们的集合K取到最优的生成树时也就是K=S的时候,这个式子才会是等式!然后我们来证明二分的正确性:当我们二分求ans的时候,对于我们当前的比率x,一定有这三种情况:

\(1.\) \(x>ans\)

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

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

\(2.\) \(x=ans\)

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

\(3.\) \(x<ans\)

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

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

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

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

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

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

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

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

总复杂度:\(O(m *logm*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 intusing 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;
}

转载于:https://www.cnblogs.com/812-xiao-wen/p/10367014.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/249663.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTTP协议学习笔记

1.HTTP协议简介 &#xff08;1&#xff09;客户端连上web服务器后&#xff0c;若想获得web服务器中的某个web资源&#xff0c;需遵守一定的通讯格式&#xff0c;HTTP协议用于定义客户端与web服务器通迅的格式。 &#xff08;2&#xff09;HTTP是hypertext transfer protocol&…

defer和async的原理与区别

上一篇刚转载了一篇有关于网站性能优化的文章&#xff0c;其中提及到了页面的加载和渲染的过程&#xff0c;提到了defer和async的相关区别&#xff0c;但是本人在此之前并没有深究其中的区别。 defer和async是script标签的两个属性&#xff0c;用于在不阻塞页面文档解析的前提…

一些奇妙的线段树操作

学过数据结构和会做题完全是两个概念orz 各种各样的题目都应该见识一下 简单的目录&#xff1a; 最大连续长度 吉司机线段树 线段树合并/分裂 最大连续长度问题 典型题目&#xff1a;HDU 3911 &#xff08;$Black$ $And$ $White$&#xff09; 题目大意&#xff1a;有一个长度为…

微服务实践沙龙-上海站

微服务的概念最早由Martin Fowler与James Lewis于2014年共同提出&#xff0c;核心思想是围绕业务能力组织服务&#xff0c;各个微服务可被独立部署&#xff0c;服务间是松耦合的关系&#xff0c;以及数据和治理的去中心化管理。微服务能够帮助企业应对业务复杂、频繁更新以及团…

Spring的refresh()方法调用过程

Spring的refresh()方法调用过程 refresh()是Spring中比较核心的方法&#xff0c;Spring所有的初始化都在这个方法中完成 具体代码如下 public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this co…

Web数据存储之localStorage和sessionStorage

Web数据存储之localStorage和sessionStorage 学习前端以来&#xff0c;自己了解有localStorage和sessionStorage的相关存储的知识&#xff0c;也有实践过&#xff0c;但是之前只限于能用的基础上&#xff0c;但最近看了一本书&#xff0c;深入了解了localStorage和sessionStor…

(四)RabbitMQ消息队列-服务详细配置与日常监控管理

&#xff08;四&#xff09;RabbitMQ消息队列-服务详细配置与日常监控管理 原文:&#xff08;四&#xff09;RabbitMQ消息队列-服务详细配置与日常监控管理RabbitMQ服务管理 启动服务&#xff1a;rabbitmq-server -detached【 /usr/local/rabbitmq/sbin/rabbitmq-server -deta…

oracle中delete、truncate、drop的区别 (转载)

一、delete 1、delete是DML&#xff0c;执行delete操作时&#xff0c;每次从表中删除一行&#xff0c;并且同时将该行的的删除操作记录在redo和undo表空间中以便进行回滚&#xff08;rollback&#xff09;和重做操作&#xff0c;但要注意表空间要足够大&#xff0c;需要手动提交…

前端开发工程化探讨--基础篇(长文)

转载自UC资深前端工程师张云龙的github 喂喂喂&#xff0c;那个切图的&#xff0c;把页面写好就发给研发工程师套模板吧。 你好&#xff0c;切图仔。 不知道你的团队如何定义前端开发&#xff0c;据我所知&#xff0c;时至今日仍然有很多团队会把前端开发归类为产品或者设计岗…

Python读取Json字典写入Excel表格的方法

需求&#xff1a; 因需要将一json文件中大量的信息填入一固定格式的Excel表格&#xff0c;单纯的复制粘贴肯定也能完成&#xff0c;但是想偷懒一下&#xff0c;于是借助Python解决问题。 环境&#xff1a; Windows7 Python2.7 Xlwt 具体分析&#xff1a; 原始文件为json列表&am…

Spring-BeanFactory源码分析

正式进入Spring 源码分析这个模块了&#xff0c;对于spring这个庞大的工程&#xff0c;如果要一点点的完全分析是非常困难的&#xff0c;对于应用型框架&#xff0c;我还是偏向于掌握思想或者设计&#xff0c;而不是记住代码&#xff0c;对于初次看spring源码&#xff0c;相信大…

Linux查看修改时间、时区

同步网络时间 yum install ntpntpdate time.nist.gov timedatectl set-timezone Asia/Shanghai如果上面time.nist.gov服务器同步不了&#xff0c;可以换下面几个时间服务器试试&#xff1a;time.nist.govtime.nuri.net0.asia.pool.ntp.org1.asia.pool.ntp.org2.asia.pool.ntp.o…

我所知道的HTTP和HTTPS

摘要&#xff1a;相比之前的传输协议&#xff0c;HTTP/2在底层方面做了很多优化。有安全、省时、简化开发、更好的适应复杂页面、提供缓存利用率等优势&#xff0c;阿里云早在去年发布的CDN6.0服务就已正式支持HTTP/2&#xff0c;访问速度最高可提升68%。 写在前面 超文本传输…

sql server常用性能计数器

https://blog.csdn.net/kk185800961/article/details/52462913?utm_sourceblogxgwz5 https://blog.csdn.net/kk185800961/article/details/27657239 以下部分转自&#xff1a;http://www.cnblogs.com/zhijianliutang/p/4174697.html 常规计数器 收集操作系统服务器的服务器性能…

Python中正反斜杠('/'和'\')的意义

刚刚在学习些测试报告的时候&#xff0c;出现一个路径的问题&#xff0c;找了很久的原因&#xff0c;竟然是少了一个反斜杠引起的&#xff0c;在此顺便记录一下正反斜杠的作用。 在Python中&#xff0c;记录路径时有以下几种写法&#xff0c;如&#xff1a;&#xff08;大家都知…

什么是IOC容器

1.IOC不是一种技术&#xff0c;只是一种思想&#xff0c;一个重要的面向对象编程的法则&#xff0c;它能指导我们如何设计出松耦合&#xff0c;更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象&#xff0c;从而导致类与类之间高耦合&#xff0c;难于测试&#x…

Jenkins配置与使用

Jenkins是一个开源软件项目&#xff0c;旨在提供一个开放易用的软件平台&#xff0c;使软件的持续集成变成可能。Jenkins是基于Java开发的一种持续集成工具&#xff0c;用于监控持续重复的工作&#xff0c;功能包括&#xff1a;1、持续的软件版本发布/测试项目。2、监控外部调用…

fastDFS使用

fastDFS : 分布式文件系统C语言开发,fastDFS为互联网量身定制,考虑到了冗余备份,负载均衡,线性扩容...很容易搭建集群文件存储系统.存储在fastDFS图片:相当于存储在本地磁盘一样访问图片:相当于访问本地磁盘存储结构:组名/虚拟磁盘路径/动态生成文件名.扩展名192.168.100.20/gr…

本地环境用eclipse搭建spring源码环境

对于JAVA和.NET开发人员来讲Spring框架并不陌生&#xff0c;对于想进行spring源码学习的同学来讲&#xff0c;在本地下载和构建spring项目很有必要。以下简要说明下Spring源码的下载和在eclipse下的构建方式。 工具/原料 JDK Eclipse 我们需要从源码库下载Spring的源码文件到本…