網路流入門 用於最大流的Dinic演算法

2021-07-10 18:10:59 字數 3452 閱讀 4517

posted 

2023年05月2日

by comzyh

「網路流博大精深」—sideman語

感謝whd的大力支援

最早知道網路流的內容便是最大流問題,最大流問題很好理解:

解釋一定要通俗!

如右圖所示,有乙個管道系統,節點,有向管道,即有向圖一張. [1]是源點,有無限的水量,[4]是匯點,管道容量如圖所示.試問[4]點最大可接收的水的流量?

這便是簡單的最大流問題,顯然[4]點的最大流量為50

死理性派請注意:流量是單位時間內的,總可以了吧!

然而對於複雜圖的最大流方法是什麼呢,有ek,dinic,sap,etc.下面介紹dinic演算法(看**的直接點這)

dinic演算法的基本思路:

根據殘量網路計算層次圖。

在層次圖中使用dfs進行增廣直到不存在增廣路

重複以上步驟直到無法增廣

引自nocow,相當簡單是吧…

小貼士:

一般情況下在dinic演算法中,我們只記錄某一邊的剩餘流量.

comzyh的較詳細解釋(流程) :

dinic動畫演示

用bfs建立分層圖  注意:分層圖是以當前圖為基礎建立的,所以要重複建立分層圖

用dfs的方法尋找一條由源點到匯點的路徑,獲得這條路徑的流量i 根據這條路徑修改整個圖,將所經之處正向邊流量減少i,反向邊流量增加i,注意i是非負數

重複步驟2,直到dfs找不到新的路徑時,重複步驟1

注意(可以無視):

對於反向弧(反向邊)的理解:

這一段不理解也不是不可以,對於會寫演算法沒什麼幫助,如果你著急,直接無視即可.

先舉乙個例子(如右圖):

在這幅圖中我們首先要增廣1->2->4->6,這時可以獲得乙個容量為2的流,但是如果不建立4->2反向弧的話,則無法進一步增廣,最終答案為2,顯然是不對的,然而如果建立了反向弧4->2,則第二次能進行1->3->4->2->5->6的增廣,最大流為3.

comzyh對反向弧的理解可以說是」偷梁換柱「,請仔細閱讀:在上面的例子中,我們可以看出,最終結果是1->2->5->6和1->2->4->6和1->3->4->6.當增廣完1->2->4->5(代號a)後,在增廣1->3->4->2->5->6(代號b),相當於將經過節點2的a流從中截流1(總共是2)走2->5>6,而不走2->4>6了,同時b流也從節點4截流出1(總共是1)走4->6而不是4->2->5->6,相當於ab流做加法.

簡單的說反向弧為今後提供反悔的機會,讓前面不走這條路而走別的路.

alwa同學非要我給他的文章加乙個鏈結,大家可以看看他的文章: 有關網路流中的反向弧和增廣路

dinic演算法的程式實現

最大流演算法一直有乙個入門經典題:poj 1273 或者是ucaco 4_2_1 來自nocow(中文) 這兩個是同乙個題

給出這道題的**:

[cpp]view plain

copy

#include 

#include 

#include 

#include 

#define min(x,y) ((x

using

namespace

std;  

const

intmax=0x5fffffff;

//int

tab[250][250];

//鄰接矩陣 

intdis[250];

//距源點距離,分層圖 

intq[2000],h,r;

//bfs佇列 ,首,尾 

intn,m,ans;

//n:點數;m,邊數 

intbfs()  

}  if(dis[n]>0)  

return

1;  

else

return

0;//匯點的dis小於零,表明bfs不到匯點 

}  //find代表一次增廣,函式返回本次增廣的流量,返回0表示無法增廣 

intfind(

intx,

intlow)

//low是源點到現在最窄的(剩餘流量最小)的邊的剩餘流量

return

0;  

}  int

main()  

ans=0;  

while

(bfs())

//要不停地建立分層圖,如果bfs不到匯點才結束 

printf("%d\n"

,ans);  

}  system("pause"

);  

}  

另一道題目是poj1742 使用鄰接表,採用當前弧優化

[cpp]view plain

copy

#include 

#include 

#include 

#include 

#include 

using

namespace

std;  

intn, np, nc, m;  

struct

edge  

edge(int

u, int

v, int

cap): u(u), v(v), cap(cap) {}  

} es[150 * 150];  

intr, s, t;  

vector

> tab[109]; 

// 邊集

intdis[109];  

intcurrent[109];  

void

addedge(

intu, 

intv, 

intcap)  

intbfs()  

}  }  return

dis[t] 

// 返回是否能夠到達匯點

}  int

dinic(

intx, 

intmaxflow)  

}  }  return

0; // 找不到增廣路 退出

}  int

dinic()  

return

ans;  

}  int

main()  

for(int

i = 0; i 

for(int

i = 0; i 

printf("%d\n"

, dinic());  

}  return

0;  

}  

網路最大流入門

網路最大流是網路流中最基礎也是最重要的部分,後邊的許多模型也都是由最大流問題引申而來的 在研究這個問題之前,讓我們先來學習一下前置知識 設 f u,v 表示邊 u,v 的當前容量上限 設 c u,v 表示邊 u,v 的最大容量上限 如果網路流圖中的流量滿足 則稱該流為乙個可行流 增廣 即增加一條路徑...

網路流的最大流入門(從普通演算法到dinic優化)

網路流 network flows 是一種模擬水流的解決問題方法,與線性規劃密切相關。網路流的理論和應用在不斷發展。而我們今天要講的就是網路流裡的一種常見問題 最大流問題。最大流問題 maximum flow problem 一種組合最優化問題,就是要討論如何充分利用裝置的能力,使得運輸的流量最大,...

poj 1273 EK最大流入門題

題意 給n條邊,從 fr 到 to,有乙個容量 num。然後問從1 流到 m,最多能流多少。解析 用ek求最大流,資料量比較小。include include include include include include include include include include includ...