網路最大流
眾所周知,網路流是圖論的乙個很重要的內容,也很有難度(主要難在建模)。
網路流的基礎概念這裡提一下:
容量網路:設g(v,e),是乙個有向網路,在v中指定了乙個頂點,稱為源點(記為vs),以及另乙個頂點,稱為匯點(記為vt);對於每一條弧屬於e,對應有乙個權值c(u,v)>0,稱為弧的容量.通常吧這樣的有向網路g稱為容量網路.
這裡主要講一下網路流最簡單的乙個分支:網路最大流。
什麼是網路最大流?
通俗的說,如果把網路流比作水流,源點比作水龍頭,匯點比作農田,邊表示水管,那麼,網路最大流表示的就是水龍頭放水經過自來水管能夠灌溉農田的最大水量。路途中其流量必然不能超過管的容積(否則管就爆了)。
下面給出一張圖理解(字有點醜,不要介意):
s為源點,t為匯點,
如圖,有s->a->c->t,經過容量為1,7,2的邊,路徑最大流為1(路徑中最小的邊)。
s->c->t,經過容量為4, 2的邊,但容量為2的邊剩餘容量為0,所以流為1,
s->b->c->t,經過容量為6,2,2的邊,路徑c->t中已經沒有容量剩餘,所以流為0,
s->b->e->t,經過容量為6,1,4的邊,路徑b->e中流最大為1,所以流為1.
所以,這張圖的網路最大流為1+1+0+1 = 3.
怎麼求網路最大流?
由定義,非常自然的,我們可以求出源點到匯點每條路徑中水管容積最小的管的容積(水量不能超過每一條管的容積),累加這些路徑的答案。
當圖中不再存在增廣路(即每一條路徑中有一條邊內沒有容量剩餘)時,就求出了網路最大流。
由此,我們推出了ek(edmonds-karp)演算法。
ek演算法
基於剛才的分析,我們可以通過bfs不斷尋找增廣路,直至圖中不存在增廣路為止。
在每輪尋找增廣路的過程中,ek演算法只考慮圖中所有f(x, y) < c(x, y)的邊,用bfs找到任意一條從s到t的路徑,同時計算出路徑上剩餘容量的最小值minf, 則網路的流量可以增加minf。
具體實現步驟如下:
(1) bfs尋找增廣路,若能找到,轉步驟(2).否則轉步驟(3)
(2) 更新剩餘容量,將流累加.
(3) 輸出累加的流,即為最大流
。**如下:
1 #include2時間複雜度為o(n*m*m),實際運用中遠遠達不到這個上界,效率較高,一般能夠處理10^3 ~ 10^4 規模的網路。#define ll long long34
using
namespace
std;56
const
int inf = 1
<< 29, n = 1000010;7
8int head[n], cnt = 1;9
int n, m, s, t, maxflow = 0;10
struct node e[n];
1112
void add(int x, int y, int
z)16
intv[n], incf[n], pre[n];
17bool
bfs()33}
34}
35return0;
36}37void update()
45 maxflow +=incf[t];46}
47int
main()
57while
(bfs()) update();
58 printf("
%d\n
", maxflow);
59return0;
60 }
對ek演算法的優化——dinic演算法
我們發現,ek演算法每輪可能會遍歷整個殘量網路,但只找出一條增廣路,還有優化的空間。
我們不妨做乙個優化,每次求完增廣路後,構造分層圖,刪去已經標記的點,這樣就避免了重複,節省了時間。
dinic 演算法核心思想:
首先bfs,在殘量網路上構造分層圖。
然後對每乙個分層圖分別dfs尋找增廣路,實時更新剩餘容量。
(1)初始化容量網路和網路流。
(2)構造殘留網路和層次網路,若匯點不再層次網路中,則演算法結束。
(3)在層次網路中用一次dfs過程進行增廣,dfs執行完畢,該階段的增廣也執行完畢。
(4)轉步驟(2)。
具體**如下:
1 #include2dinic演算法時間複雜度為(n*n*m),實際上遠遠達不到這個上界,可以說是比較容易實現的的效率最高的網路流演算法之一,一般能處理10^4~10^5的網路。#define ll long long34
using
namespace
std;56
const
int inf = 1
<<29, n = 1000010;7
int head[n], cnt = 0;8
intn, m, s, t, maxflow;
9struct node e[n];
10 queue q;
11void add(int x, int y, int
z)15
intd[n];
16bool bfs()29}
30}31return0;
32}3334
int dinic(int x, int flow)47}
48return flow -rest;49}
50int
main()
61int flow = 0;62
while(bfs())//
bfs 構造分層圖,直到流到匯點後分層完畢。
63while(flow = dinic(s, inf)) maxflow += flow; //
累加每一層的流
64 printf("
%d\n
", maxflow);
65return0;
66 }
總結
這就是求網路最大流的兩個主要演算法(我不會其他演算法qwq)。
其實網路流除了網路最大流之外,還有最大流最小割,最小費用最大流,最大費用最大流等,以後再敘述。
網路流 最大流 Dinic演算法的初步認識
網路流 最大流 dinic演算法的初步認識 目前部落格轉移 簡單說一說 有乙個起點 源點 和乙個終點 匯點 它們之間用很多直徑大小不一的管子連在一起,為什麼要用大小不一的管子,假如這些都是水管 那麼你要做的就是 算出從源點到匯點最大可以流入多少水。顯然,對於一條路上,它的最大流是這條路上直徑最小的管...
網路流初步 最大流問題
形象理解 就好比你家小區的供水系統,所有的水都來自自來水廠,經過管道運輸到你小區的使用者,再經過下水道去往廢水處理廠,整個過程中,自來水廠就好比源點,整個網路中的管道大小限制就好比容量,其中流過的水量好比流量,而最終的處理廠就好比匯點。網路流 所有弧上流量的集合f 稱為該容量網路的乙個網路流.定義 ...
網路最大流演算法 Dinic演算法及優化
dinic在資訊學奧賽中是一種最常用的求網路最大流的演算法。它憑藉著思路直觀,難度小,效能優越等優勢,深受廣大oier青睞 dinic 演算法屬於增廣路演算法。它的核心思想是 對於每乙個點,對其所連的邊進行增廣,在增廣的時候,每次增廣 極大流 這裡有別於ek演算法,ek演算法是從邊入手,而dinic...