[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.pswp.cn/news/249663.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/249663.shtml
英文地址,請注明出處:http://en.pswp.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的源碼文件到本…