網路流 有上下界的最大流

2021-10-18 19:02:40 字數 4043 閱讀 9124

有上下界的含義:每條管道的流量必須在範圍 [l,r] 內,即在普通最大流問題上增加了下界限制。

主要分為無源點匯點和有源點匯點兩類問題。

此類問題一般為:給n個點,及m根pipe,每根pipe是用來流淌液體的,單向的,每時每刻每根pipe流進來的物質要等於流出去的物質,要使得m條pipe組成乙個迴圈體,裡面流淌物質。並且滿足每根pipe一定的流量限制,範圍為[li,ri].即要滿足每時刻流進來的不能超過ri(最大流問題),同時最小不能低於li。

解決:普通的最大流可以視作下界為0,上界為容量。所以此時讓所有管道的下界變為0,上界變為r-l。但是這樣的話流量不守恆(流入的不等於流出的),需要更改建圖方法,尋找附加流來滿足守恆。

此時新增超級源點s和匯點t,定義du[maxn]來記錄每個節點的流量情況。

du[i] = in[i] (i節點所有入流下界之和) - out[i] (i節點所有出流下界之和).

當du[i]大於0時,從 s 到 i 連一條流量為du[i]的邊;

當du[i]小於0時,從 i 到 t 連一條流量為-du[i]的邊;

最後對(s,t)求最大流即可,求出的最大流為附加最大流,此時每條管道的實際流量還要加上之前為了改造而修改的下界l。

當附加流最大流==所有的du>0之和時,有可行解(可行流)(可以使流量守恆)。

例題:reactor cooling(sgu-194)

//dinic

#include

#define

lllong

long

#define

iosstd::ios::

sync_with_stdio

(false

);cin.

tie(0)

;cout.

tie(0)

;#define

debug

cout<<

",here\n";#

define

maxn

250using

namespace std;

struct

edge

};edge a[maxn]

[maxn]

;vectorlink[maxn]

;vector

>pipe;

ll ceng[maxn]

;//注意dn記錄每條邊的下界資訊,不能用點的maxn,不然會陣列太小

ll du[maxn]

,dn[maxn*maxn*2]

;ll n,m,s,t,u,v,l,c,maxn,ans=0;

ll bfs()

//最大流:構建層級網路,一次bfs就行了,很簡單}}

if(ceng[t]

)return1;

//最大流:能構建,繼續之後的dfs

return0;

//最大流:不能構建更多了,沒有更多的增廣路了

}//最大流:有當前弧優化

ll dfs

(ll now,ll minflow)

ll ret=

0,minflow2;

for(

auto

& i:link[now])}

return ret;

//最大流:返回從這個節點開始之後找到的所有增廣路的流量之和

}int

main()

);} s=

0;t=n+1;

ll totdu=0;

for(ll i=

1;i<=n;i++

)else

if(du[i]

<0)

if(du[i]

>

0)totdu+=du[i]

;//用於判斷是否有可行解

}while

(bfs()

)if(ans!=totdu)

else

}return0;

}

源點 s ,匯點 t 。

同樣,因為有下界,所以先判斷是否有可行流,可參考無源匯點的可行流判斷。但有源匯點如何轉化為無源匯的迴圈流圖?增設一條從 t 到 s 沒有下界且容量為無窮的邊 即可。之後再新增超級源匯點ss和tt,和無源匯點一樣判斷可行流。

當有可行流時,再原封不動地以 s,t 為源匯點跑一次最大流,結果即為最終答案。

有源匯上下界最大流只需要求解可行流並判斷可行後,原封不動地進行一次最大流,這個最大流就是答案(不用再加之前的可行流流量)。因為超級源匯的邊全部滿流不會影響,而原可行流流量全部在t-s的反向邊上,跑最大流時剛好會算進去,這樣跑出來的最大流就是最終答案。

例題:【模板】有源匯上下界最大流

//dinic

#include

#define

lllong

long

#define

iosstd::ios::

sync_with_stdio

(false

);cin.

tie(0)

;cout.

tie(0)

;#define

debug

cout<<

",here\n";#

define

maxn

1505

using

namespace std;

struct

edge

};edge a[maxn]

[maxn]

;vectorlink[maxn]

;ll ceng[maxn]

;//無源匯:注意dn記錄每條邊的下界資訊,不能用點的maxn,不然會陣列太小

ll du[maxn]

;ll g,c,d;

ll n,m,u,v,ans=0;

const ll inf=

2147483648

;struct

dinic

ll bfs()

//最大流:構建層級網路,一次bfs就行了,很簡單}}

if(ceng[t]

)return1;

//最大流:能構建,繼續之後的dfs

return0;

//最大流:不能構建更多了,沒有更多的增廣路了

}//最大流:有當前弧優化

ll dfs

(ll now,ll minflow)

ll ret=

0,minflow2;

for(

auto

& i:link[now])}

return ret;

//最大流:返回從這個節點開始之後找到的所有增廣路的流量之和

} ll maxflow

(ll s,ll t,ll minflow)

return tmp;}}

;dinic solver;

intmain()

}/*例題特殊建圖,不具代表性*/

for(ll i=

1;i<=m;i++

)for

(ll i=

1;i<=n;i++)}

/**/

solver.

addedge

(t,s,inf)

;//新增t到s的無窮容量邊

ll totdu=0;

for(ll i=

1;i<=t;i++

)else

if(du[i]

<0)

if(du[i]

>

0)totdu+=du[i]

;//無源匯:用於判斷是否有可行解

} ans=solver.

maxflow

(ss,tt,inf);if

(ans!=totdu)

else

}return0;

}

參考:

有上下界的網路流學習筆記

網路流各種題型應用及解決方法

有上下界網路流

前言 下面寫得只是一些十分基礎的東西,是給我以後自己看的,想要徹底弄明白這個內容,推薦去看liu runda。注 為了方便,下面所有的 x,y,l,r 都表示一條從x連向y,流量下界為l,流量上界為r的邊。問題簡述 給出乙個有向圖,每條邊有流量上下界,沒有源點和匯點,要求找到一種流的方法,使得每個點...

上下界 最大流

做法 1 有源彙編成無源匯 t s,0,infmax 2 ss tt 連線個點 intout 0 ss i,0,inout i inout 0 i,tt,0,inout i 3 然後跑一片最大流 max dinic ss,tt 之後的這步很重要 head ss head tt 1 刪除ss 和 tt...

有上下界的網路流

有上下界的網路流 這幾天看了周源的 一種簡易的方法求解流量有上下界的網路中網路流問題 並完成了 sgu 194 zoj 2314 reactor cooling,sgu 176 flow construction 和hoj 2135 poj 2396 budget三道題。作為周源文章中提到的求解上下...