最大流Dinic演算法介紹

2021-09-25 07:45:41 字數 2359 閱讀 5405

本文**:

dinic演算法本身,自然是解決最大流(普通最大流,最大流最小割)的演算法。通過處理,也可以解決二分圖的最大匹配(下文介紹),最大權閉合圖。

演算法介紹:介紹dinic之前,我們先介紹一下最大流。在最大流的題目中,圖被稱為"網路",每條邊的邊權被稱作"流量",有乙個起點(源點)和乙個終點(匯點)。我們要求的最大流,可以這樣形象地理解:源點有乙個水庫,裡面有無限噸水(qwq),匯點也有乙個水  庫,希望得到最多的水。我們假設每個河道一天只能輸水n噸(及網路流中的流量),求解匯點最多能的到幾噸水。再給乙個正式的定義:最大流是指網路中滿足弧流量限制條件和平衡條件且具有最大流量的可行流

下面我們正式介紹dinic:

首先引出網路流演算法中的鏈,給個正式定義:鏈是網路中的乙個頂點序列,這個序列中前後兩個頂點有弧相連(其實我認為這個定義無關緊要,所以重點看下面弧的定義)。

弧 :弧分為兩種,第一種是前向弧是指方向和鏈一致的弧(簡單的說就是輸入的邊)---前向弧,第二種弧是指方向和鏈不一致的弧(簡單的說就是輸入的邊反一反)---後向弧。

好了接下來要引出乙個網路流演算法的重要概念

增廣路

給個正式的定義:

1、增廣路是一條鏈

2、鏈上的前向弧都是非飽和弧 

鏈上的後向弧都是非零弧

3、鏈是由源點到匯點的

總結一下:額...這聽起來好像啥都沒說(滑稽)

談談我的理解:

增廣路就是一條從源點到匯點的路,並且帶有乙個值,表示該增廣路的最大流量,該值得大小取決於該增廣路中擁有最小流量的邊。

剩餘網路

由反向弧組成的網路,關於反向弧的權的問題,後文會介紹。

說了一大堆,下面正式介紹dinic演算法

dinic演算法的大致步驟

1、建立網路(包括正向弧和反向弧(初始邊權為0)),將總流量置為0

2、構造層次網路(怎麼又有新概念 t_t)

簡單的說,就是求出每個點u的層次,u的層次是從源點到該點的最短路徑(注意:這個最短路是指弧的權都為1的情況下的最短路),若與源點不連通,層次置為-1

一遍bfs輕鬆解決

3、判斷匯點的層次是否為-1

是:再見,演算法結束,輸出當前的總流量

否:下一步

4、用一次dfs完成所有增廣,增廣是什麼呢?

增廣(我的理解):通過dfs找上述的增廣路,找到了之後,將每條邊的權都減去該增廣路中擁有最小流量的邊的流量,將每條邊的反向邊的權增加這個值,同時將總流量加上這個值

dfs直到找不到一條可行的從原點到匯點的路

5、goto 步驟2

細節處理,如何快速找到一條邊的反向邊:邊的編號從0開始,反向邊加在正向邊之後,反向邊即為該點的編號異或1

複雜度:理論上來說,最慢應該是o((n^2)*m),n表點數,m表邊數,實際上呢,應該快得不少

**例項:(參見洛谷p3376)

弧優化

在dfs的時候記錄當前已經計算到第幾條邊了,避免重複計算。

然後在下一次構建層次網路的注意將head陣列還原

* 使用當前弧優化

#include #include #include #include using namespace std;

const int max = (1ll << 31) - 1;

int read()

struct edge edges[210000];

int cur[10010], head[10010], edge_num = -1;

int n, m, s, t;

void addedge2(int from, int to, int dis)

void addedge(int from, int to, int dis)

int d[10010];

int dfs(int u, int flow)

}if (!_flow) d[u] = -1;

return _flow;

}bool bfs()}}

return (d[t] != -1);

}void dinic()

printf("%d", max_flow);

}int main()

dinic();

return 0;

}

1、裸的最大流

2、二分圖的最大匹配:建乙個點s,連到二分圖的集合a中;建乙個點t,連到二分圖的集合b中。再將所有的集合a中的點與集合b中的點相連。全部邊權設為1,跑一遍最大流,結果即為二分圖的最大匹配

主要問題:

為什麼要建立反向邊?

最大流 Dinic演算法

ford fulkerson演算法是通過深度優先搜尋尋找增廣路,並沿著它增廣。與之相對,dinic演算法總是尋找最短的增廣路,並沿著它增廣。因為最短增廣路的長度在增廣過程中始終不會變短,所以無需每次都通過寬度預先搜尋來尋找最短增廣路。我們可以先進行一次寬度優先搜尋,然後考慮由進距離頂點指向遠距離頂點...

Dinic演算法求最大流

include using namespace std const int oo 1e9 無窮大 const int maxm 111111 邊的最大數量,為原圖的兩倍 const int maxn 999 點的最大數量 int node,src,dest,edge node節點數,src源點,de...

最大流模版Dinic演算法

網路流的演算法有很多,最基礎的為ek演算法,他的時間複雜度為o n m 2 dinic演算法的時間複雜為o m n 2 dinic演算法是現構造層次圖,然後用阻塞流來增廣。構造層次圖有乙個bfs,增廣是用dfs來寫。詳細的講述請參考 劉汝佳寫的 演算法競賽入門經典訓練指南 大白書 include i...