網路最大流 附當前弧優化

2021-09-24 05:41:24 字數 3208 閱讀 7114

一篇巨佬的網路流建模

網路最大流問題就是給你乙個有向圖,告訴你乙個源點與乙個匯點,並給每一條邊乙個最大流量,需要你求出從源點最多能夠發出多少單位流量到匯點(哎呀我也說不清,就是給你一些或大或小的管道(每個管道都有最大秒流量),一些中轉站,一座供水塔以inf單位每秒的速度供水,問你家每秒最多得到多少單位水(中轉站、供水塔、你家由管道連通))

很顯然看起來我們可以從源點跑dfs,只要到下一節點的邊的邊權》0就跑到下一節點,一路跑過去,直到匯點,然後答案加上這一路上最小的管道流量,這一條路徑上所有管道減去這個流量,然後就沒了。

但是這樣子是有問題的。(藍模板怎麼可能這麼簡單)

舉個栗子:(將dfs路徑用紅色表示)

然後你會發現這樣的答案是2,然而正確的答案是4(s-2-t,s-3-t)

(不要說你的存邊是2-t比2-3優先,調個位置就卡掉了) 

為什麼會這樣?

因為上圖中第一條dfs路徑把原本應是第二條路徑的一條邊給「占用」了。

計算機可不是人,它無法判斷到底該怎麼跑dfs,所以這時候就需要我們人為地給計算機乙個「反悔」的機會。

重點:怎麼讓計算機「反悔」?

給每條邊建邊權為0的反向邊,當每次跑到匯點時,在回溯給dfs路徑上的邊權減去最小邊權的時候還要給反向邊加上最小邊權。

先看效果:

然後答案就神奇地變成4了! 

為什麼?

用整體的思想來看:如果我正著經過一條邊,再反著經過,是不是相當於沒經過?好吧,我承認這不是很好理解

這一種「抵消」的思想應用十分廣泛,比如洛谷p1792 [國家集訓隊]種樹,就是一種利用類似「抵消」的方法來實現的可反悔的貪心。

沒理解也沒關係,反正就是要反向建邊,題做多了就理解了qaq

使用了這種「抵消」思想的dfs,大概就是所謂的ek演算法了。(即不停的尋找增廣路然後操作)

然後再介紹一種優化演算法:dinic演算法(本質上其實差不多,只不過是一次尋找多條增廣路並更新圖)

ps:增廣路即能夠使答案增加的dfs路徑

大概步驟就是:

1.bfs——給之後尋找增廣路的dfs提供乙個bfs序作為擴充套件增廣路的依據,同時判斷是否還存在增廣路(如果遍歷不到匯點,就退出輸出答案)。

2.dfs——尋找增廣路(注意這裡一次尋找了多條)並更新答案。

3.重複1

dinic的**實現:(貼上我洛谷p3376 【模板】網路最大流的**)

#include#include#include#define maxn 20010

#define maxm 200010

#define inf 0x3f3f3f3f

using namespace std;

int bg[maxn],nt[maxm],to[maxm],w[maxm],e=1;

int dep[maxn],q[maxn],n,m,s,t,ans;

void insert(int x,int y,int z)

void bfs()

}}int dfs(int x,int s)

}return res;

}int main()

while (1)

printf("%d\n",ans);

return 0;

}

洛谷p2764 最小路徑覆蓋問題

我的題解qwq

洛谷p3355 騎士共存問題

暫時我沒寫題解qaq

附:當前弧優化

聽名字似乎是乙個很高階的東西,但其實很簡單,就幾句話。。。

我們維護乙個now陣列,在每次dfs前把鏈式前向星的bg陣列(或者是head)拷貝乙份到now上,然後在dfs列舉邊找下乙個節點時迴圈列舉邊的編號不再從bg[x]開始了,而從now[x]開始。而now[x]不斷地更新,即i迴圈到哪,now[x]都更新為i。(具體實現還是看**吧,我的語言表達能力一向不強)

這樣子可以大大提公升程式效率。

**:

#include#include#include#define maxn 20010

#define maxm 200010

#define inf 0x3f3f3f3f

using namespace std;

int bg[maxn],nt[maxm],to[maxm],w[maxm],e=1;

int dep[maxn],q[maxn],n,m,s,t,ans,now[maxn];

void insert(int x,int y,int z)

void bfs()

}}int dfs(int x,int s)

now[x]=i;

}return res;

}int main()

while (1)

printf("%d\n",ans);

return 0;

}

實測效率截圖o_o!:

優化之前:

之後:

至於這個優化的正確性,蒟蒻引用一句很6的話(畢竟我描述不出來)——

「對於一次bfs而言,它確定的層次圖中每條邊若已經被走完了,那麼它就不可能再帶來增廣,下一次就直接從這條最後沒走完的邊走就可以了。」

網路流 最大流 dinic 當前弧優化 模板

用法 在原有向圖的基礎上,增加源點s和匯點t,並將s與左子集建邊,t與右子集建邊 邊權都設為1,則就是求二分圖最大匹配 右子集與t的邊權大於1,則就是求二分圖最大多重匹配 模板 const int n 210 struct edge edge n n 邊數 int head n cnt void a...

模板 網路最大流 最大流

給出乙個網路圖,以及其源點和匯點,求出其網路最大流。in put role presentation inp utin put4 5 4 3 4 2 30 4 3 20 2 3 20 2 1 30 1 3 40ou tput role presentation out puto utpu t50最大...

模板 網路最大流 最大流

給出乙個網路圖,以及其源點和匯點,求出其網路最大流。in put role presentation inp utin put4 5 4 3 4 2 30 4 3 20 2 3 20 2 1 30 1 3 40ou tput role presentation out puto utpu t50最大...