loj 115 無源匯有上下界可行流

2021-08-09 11:23:21 字數 2492 閱讀 3914

參考部落格:

模型:乙個網路,求出乙個流,使得每條邊的流量必須》=li且<=hi,每個點必須滿足總流入量=總流出量(流量守恆)(這個流的特點是迴圈往復,無始無終).

這個演算法是有上下界網路流演算法的基礎,只要深刻理解這個演算法其他演算法也就水到渠成,因此我用大篇幅力圖將這個演算法的思想和細節闡述清楚.

可行流演算法的核心是將乙個不滿足流量守恆的初始流調整成滿足流量守恆的流.

流量守恆,即每個點的總流入量=總流出量

如果存在乙個可行流,那麼一定滿足每條邊的流量都大於等於流量的下限.因此我們可以令每條邊的流量等於流量下限,得到乙個初始流,然後建出這個流的殘量網路.(即:每條邊的流量等於這條邊的流量上限與流量下限之差)這個初始流不一定滿足流量守恆,因此最終的可行流一定是在這個初始流的基礎上增大了一些邊的流量使得所有點滿足流量守恆.

因此我們考慮在殘量網路上求出乙個另不滿足流量守恆的附加流,使得這個附加流和我們的初始流合併之後滿足流量守恆.即:

如果某個點在所有邊流量等於下界的初始流中滿足流量守恆,那麼這個點在附加流中也滿足流量守恆,

如果某個點在初始流中的流入量比流出量多x,那麼這個點在附加流中的流出量比流入量多x.

如果某個點在初始流中的流入量比流出量少x,那麼這個點在附加流中的流出量比流入量少x.

可以認為附加流中一條從u到v的邊上的乙個流量代表將原圖中u到v的流量增大1

x的數值可以列舉x的所有連邊求出.比較方便的寫法是開乙個陣列a,a[i]表示i在初始流中的流入量-流出量的值,那麼a[i]的正負表示流入量和流出量的大小關係,下面就用a[i]表示初始流中i的流入量-流出量

但是dinic演算法能夠求的是滿足流量守恆的有源匯最大流,不能在原網路上直接求乙個這樣的無源匯且不滿足流量守恆的附加流.注意到附加流是在原網路上不滿足流量守恆的,這啟發我們新增一些原網路之外的邊和點,用這些邊和點實現」原網路上流量不守恆」的限制.

具體地,如果乙個點i在原網路上的附加流中需要滿足流入量》流出量(初始流中流入量《流出量,a[i]<0),那麼我們需要給多的流入量找乙個去處,因此我們建一條從i出發流量=-a[i]的邊.如果a[i]>0,也就是我們需要讓附加流中的流出量》流入量,我們需要讓多的流出量有乙個來路,因此我們建一條指向i的流量=a[i]的邊.

當然,我們所新建的從i出發的邊也要有個去處,指向i的邊也要有個來路,因此我們新建乙個虛擬源點ss和乙個虛擬匯點tt(雙寫字母是為了和有源匯網路流中的源點s匯點t相區分).新建的指向i的邊都從ss出發,從i出發的邊都指向tt.乙個點要麼有一條邊指向tt,要麼有一條邊來自ss,

指向tt的邊的總流量上限一定等於ss流出的邊的總流量上限,因為每一條邊對兩個點的a[i]貢獻一正一負大小相等,所以全部點的a[i]之和等於0,即小於0的a[i]之和的絕對值=大於0的a[i]之和的絕對值.

如果我們能找到乙個流滿足新加的邊都滿流,這個流在原圖上的部分就是我們需要的附加流(根據我們的建圖方式,「新加的邊都滿流」和」附加流合併上初始流得到流量平衡的流」是等價的約束條件).

那麼怎樣找出乙個新加的邊都滿流的流呢?可以發現假如存在這樣的方案,這樣的流一定是我們所建出的圖的ss-tt最大流,所以跑ss到tt的最大流即可.如果最大流的大小等於ss出發的所有邊的流量上限之和(此時指向tt的邊也一定滿流,因為這兩部分邊的流量上限之和相等).

最後,每條邊在可行流中的流量=容量下界+附加流中它的流量(即跑完dinic之後所加反向邊的權值).

**:#includeusing namespace std;

typedef long long ll;

namespace dinic

edge(int _u,int _v,int _cap,int _nxt):u(_u),v(_v),cap(_cap),nxt(_nxt){}

}e[maxm];

int head[maxn],dis[maxn],vis[maxn];

int tol;

void init()

void addedge(int u,int v,int cap)

bool bfs(int s,int t)

}} return dis[t]0)

if(maxflow==0)

break;

}} return ret;//找不到增廣路退出

} ll dinic(int s,int t,int n)

while(flow=dfs(s,inf,t))//一次bfs可以進行多次增廣

ans+=(ll)flow;

} return ans; }}

using namespace dinic;

int a[maxn],low[maxm];

int n,m;

bool judge()

for(int i=head[n+1];~i;i=e[i].nxt)

return true;

}void solve()

cnt=tol;

for(int i=1;i<=n;i++)

dinic(0,n+1,n+2);

if(!judge())

puts("yes");

for(int i=0;i

LOJ 115 無源匯有上下界可行流

模板題 首先把下界去掉 連邊upper lower 然後記錄每個點至少要流出的和流入的流量 下界 然後流入大於流出的連向tt,流出大於流入的連向ss 補流 然後跑最大流,如果sum flow,就代表加上的邊滿流,有答案,否則沒有 include include include include inc...

loj 115 無源匯有上下界可行流

這是一道模板題。n 個點,m 條邊,每條邊 e 有乙個流量下界 text e 和流量上界 text e 求一種可行方案使得在所有點滿足流量平衡條件的前提下,所有邊滿足流量限制。第一行兩個正整數 n m 之後的 m 行,每行四個整數 s t text text 如果無解,輸出一行no。否則第一行輸出y...

無源匯可行流 模板LOJ 115

自個設個源點s,匯點t,每個點 du i 入度 出度。du i 0時 加邊s i,邊權為du i du i 0時 加邊i t,邊權為 du i 設sum為所有 0的du i 的和 求s t的最大流,如果maxflow sum,則存在可行流,此時每條邊流掉的流量 它原本的下界就是實際的流量 dfs過程...