有上下界的含義:每條管道的流量必須在範圍 [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三道題。作為周源文章中提到的求解上下...