BZOJ3130: [Sdoi2013]费用流[最大流 实数二分]
3130: [Sdoi2013]費(fèi)用流
Time Limit:?10 Sec??Memory Limit:?128 MBSec??Special JudgeSubmit:?960??Solved:?505
[Submit][Status][Discuss]
Description
?Alice和Bob在圖論課程上學(xué)習(xí)了最大流和最小費(fèi)用最大流的相關(guān)知識(shí)。
??? 最大流問(wèn)題:給定一張有向圖表示運(yùn)輸網(wǎng)絡(luò),一個(gè)源點(diǎn)S和一個(gè)匯點(diǎn)T,每條邊都有最大流量。一個(gè)合法的網(wǎng)絡(luò)流方案必須滿足:(1)每條邊的實(shí)際流量都不超過(guò)其最大流量且非負(fù);(2)除了源點(diǎn)S和匯點(diǎn)T之外,對(duì)于其余所有點(diǎn),都滿足該點(diǎn)總流入流量等于該點(diǎn)總流出流量;而S點(diǎn)的凈流出流量等于T點(diǎn)的凈流入流量,這個(gè)值也即該網(wǎng)絡(luò)流方案的總運(yùn)輸量。最大流問(wèn)題就是對(duì)于給定的運(yùn)輸網(wǎng)絡(luò),求總運(yùn)輸量最大的網(wǎng)絡(luò)流方案。
? 上圖表示了一個(gè)最大流問(wèn)題。對(duì)于每條邊,右邊的數(shù)代表該邊的最大流量,左邊的數(shù)代表在最優(yōu)解中,該邊的實(shí)際流量。需要注意到,一個(gè)最大流問(wèn)題的解可能不是唯一的。??? 對(duì)于一張給定的運(yùn)輸網(wǎng)絡(luò),Alice先確定一個(gè)最大流,如果有多種解,Alice可以任選一種;之后Bob在每條邊上分配單位花費(fèi)(單位花費(fèi)必須是非負(fù)實(shí)數(shù)),要求所有邊的單位花費(fèi)之和等于P。總費(fèi)用等于每一條邊的實(shí)際流量乘以該邊的單位花費(fèi)。需要注意到,Bob在分配單位花費(fèi)之前,已經(jīng)知道Alice所給出的最大流方案。現(xiàn)茌Alice希望總費(fèi)用盡量小,而Bob希望總費(fèi)用盡量大。我們想知道,如果兩個(gè)人都執(zhí)行最優(yōu)策略,最大流的值和總費(fèi)用分別為多少。
Input
??? 第一行三個(gè)整數(shù)N,M,P。N表示給定運(yùn)輸網(wǎng)絡(luò)中節(jié)點(diǎn)的數(shù)量,M表示有向邊的數(shù)量,P的含義見問(wèn)題描述部分。為了簡(jiǎn)化問(wèn)題,我們假設(shè)源點(diǎn)S是點(diǎn)1,匯點(diǎn)T是點(diǎn)N。
??? 接下來(lái)M行,每行三個(gè)整數(shù)A,B,C,表示有一條從點(diǎn)A到點(diǎn)B的有向邊,其最大流量是C。
Output
第一行一個(gè)整數(shù),表示最大流的值。
第二行一個(gè)實(shí)數(shù),表示總費(fèi)用。建議選手輸出四位以上小數(shù)。
Sample Input
3 2 11 2 10
2 3 15
Sample Output
1010.0000
HINT
?
【樣例說(shuō)明】
??? 對(duì)于Alice,最大流的方案是固定的。兩條邊的實(shí)際流量都為10。
??? 對(duì)于Bob,給第一條邊分配0.5的費(fèi)用,第二條邊分配0.5的費(fèi)用。總費(fèi)用
為:10*0.5+10*0.5=10。可以證明不存在總費(fèi)用更大的分配方案。
【數(shù)據(jù)規(guī)模和約定】
??? 對(duì)于20%的測(cè)試數(shù)據(jù):所有有向邊的最大流量都是1。
??? 對(duì)于100%的測(cè)試數(shù)據(jù):N < = 100,M < = 1000。
??? 對(duì)于l00%的測(cè)試數(shù)據(jù):所有點(diǎn)的編號(hào)在I..N范圍內(nèi)。1 < = 每條邊的最大流
量 < = 50000。1 < = P < = 10。給定運(yùn)輸網(wǎng)絡(luò)中不會(huì)有起點(diǎn)和終點(diǎn)相同的邊。
?
- 第一問(wèn)不用說(shuō)了
- 假設(shè)現(xiàn)在已經(jīng)有了一個(gè)最大流的方案,那么Bob一定會(huì)把 P 的費(fèi)用全用到流量最大的那條邊上
- 也就是說(shuō)要讓最大流量的邊最小
- 二分邊的最大流看,檢查是否還能求得同樣大小的最大流
- 注意要實(shí)數(shù)二分,不能整數(shù)二分
最大流本身是一定的整數(shù),但是為滿足最優(yōu)解,某一條邊的流量可以是實(shí)數(shù)。所以這題是實(shí)數(shù)網(wǎng)絡(luò)流!
實(shí)數(shù)二分好坑.........不要m+-1,不要保留一個(gè)ans,只是簡(jiǎn)單的二分l和r行了,最后取那一個(gè)都行
// // main.cpp // sdoi2003費(fèi)用流 // // Created by Candy on 25/11/2016. // Copyright ? 2016 Candy. All rights reserved. // #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=105,M=1005,INF=1e9; const double eps=1e-5; int read(){char c=getchar();int x=0,f=1;while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}return x*f; } int n,m,p,u,v,c,s,t; struct data{int u,v,c; }a[M]; struct edge{int v,ne;double c,f; }e[M<<1]; int h[N],cnt=0; inline void ins(int u,int v,double c){cnt++;e[cnt].v=v;e[cnt].c=c;e[cnt].f=0;e[cnt].ne=h[u];h[u]=cnt;cnt++;e[cnt].v=u;e[cnt].c=0;e[cnt].f=0;e[cnt].ne=h[v];h[v]=cnt; } void build(double mid){cnt=0;memset(h,0,sizeof(h));for(int i=1;i<=m;i++) ins(a[i].u,a[i].v,min((double)a[i].c,mid)); } int cur[N]; int d[N],vis[N],q[N],head,tail; bool bfs(){memset(vis,0,sizeof(vis));memset(d,0,sizeof(d));head=tail=1;d[s]=0;vis[s]=1;q[tail++]=s;while(head!=tail){int u=q[head++];for(int i=h[u];i;i=e[i].ne){int v=e[i].v;if(!vis[v]&&e[i].c>e[i].f){d[v]=d[u]+1;vis[v]=1;q[tail++]=v;if(v==t) return 1;}}}return 0; }double dfs(int u,double a){if(u==t||a==0) return a;double flow=0,f;for(int &i=cur[u];i;i=e[i].ne){int v=e[i].v;if(d[v]==d[u]+1&&(f=dfs(v,min(a,e[i].c-e[i].f)))>0){flow+=f;e[i].f+=f;e[((i-1)^1)+1].f-=f;a-=f;if(a==0) break;}}return flow; } double dinic(){double flow=0;while(bfs()){for(int i=1;i<=n;i++) cur[i]=h[i];flow+=dfs(s,INF);}return flow; } int main(int argc, const char * argv[]) {n=read();m=read();p=read();s=1;t=n;double l=0,r=0;for(int i=1;i<=m;i++){a[i].u=read(),a[i].v=read(),a[i].c=read();ins(a[i].u,a[i].v,a[i].c);r=max(r,(double)a[i].c);}//r+=eps;double old=dinic();while(r-l>eps){double mid=(l+r)*0.5;//printf("%f %f\n",l,r); build(mid);double mx=dinic();if(fabs(mx-old)<eps) r=mid;else l=mid;}printf("%d\n%.4f",(int)old,l*p);return 0; }?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/candy99/p/6103372.html
總結(jié)
以上是生活随笔為你收集整理的BZOJ3130: [Sdoi2013]费用流[最大流 实数二分]的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: JAVA 常用框架和工具
- 下一篇: 模型驱动 ModelDriven