最大流算法 - 标号法
標(biāo)號(hào)法求最大流
圖論中網(wǎng)絡(luò)的相關(guān)概念見上篇博客
算法基本思想:
從某個(gè)初始流開始,重復(fù)地增加流的值到不能再改進(jìn)為止,則最后所得的流將是一個(gè)最大流。為此,不妨將每條邊上的流量設(shè)置為0作為初始流量。為了增加給定流量的值,我們必須找出從發(fā)點(diǎn)到收點(diǎn)的一條路并沿這條路增加流量。
當(dāng)前流為最大流的充要條件:網(wǎng)絡(luò)中不存在增廣路
最大流最小截定理:在任何網(wǎng)絡(luò)中,最大流的流量等于最小截集的容量。
整數(shù)流定理:在任何網(wǎng)絡(luò)中,如果網(wǎng)絡(luò)所有的弧容量都是整數(shù),則存在整數(shù)最大流。
明確一點(diǎn):最大流是指網(wǎng)絡(luò)中流的值達(dá)到最大,即源的出流量或匯的入流量達(dá)到最大,每段弧都有對(duì)應(yīng)的流量,而不是求網(wǎng)絡(luò)中某個(gè)路徑的流量。
把最大流算法想象成兩個(gè)運(yùn)輸站之間運(yùn)貨,兩個(gè)運(yùn)輸站之間有很多個(gè)中轉(zhuǎn)站,每個(gè)中轉(zhuǎn)站都有一個(gè)最大容量,站與站之間運(yùn)貨都有不同的運(yùn)貨量,而且中轉(zhuǎn)站不會(huì)留貨物,所以貨物的總量一定等于源站的出貨數(shù)或者匯站的進(jìn)貨數(shù)。最大流算法就是在不超過所有中轉(zhuǎn)站的容量的情況下,求最大出貨量/進(jìn)貨量以及所有中轉(zhuǎn)站之間的運(yùn)貨量。
如下圖所示,左邊是容量,右邊是流量,在如圖所示的流中,流的值達(dá)到了最大,為13,也不存在增廣路,所謂增廣路就是一條從源到匯的路徑,路徑上的所有弧非飽和(正向)或非空(反向),即一條仍能增加流量的路。
為什么說增廣路是一條仍能增加流量的路?其實(shí)不難理解,增廣路的定義如上文,路徑上的所有弧非飽和(正向)或非空(反向),反向弧的流量假設(shè)為n,實(shí)際上等價(jià)于為正向弧的流量為-n,因?yàn)閚不能小于0,所以n=0的時(shí)候,反向弧的流量雖然達(dá)到了最小,但是把他當(dāng)做正向弧的時(shí)候,流量卻達(dá)到了最大。
對(duì)于一條路徑而言,非飽和弧和非空弧都意味著該條路徑的流量沒有達(dá)到飽和。既然網(wǎng)絡(luò)中存在一條沒有達(dá)到飽和的路徑,那么網(wǎng)絡(luò)的流也沒有達(dá)到最大。這就是當(dāng)前流為最大流的充要條件,可用數(shù)學(xué)語言證明。
算法文字描述:
步驟0:將網(wǎng)絡(luò)中所有弧流量全部置0
步驟1:將源的點(diǎn)流量設(shè)為無窮大,令u=s。
步驟2:標(biāo)記 點(diǎn)vi=uv_i=uvi?=u的所有未被標(biāo)記的鄰點(diǎn)vjv_jvj?的點(diǎn)流量(BFS)。
標(biāo)記方法:若u到鄰點(diǎn)是正向弧,且流量小于容量,則點(diǎn)流量Δ(vj)Δ(v_j)Δ(vj?)取前點(diǎn)流量Δ(vi)Δ(v_i)Δ(vi?)和弧的容流量差值Cij?FijC_{ij}-F_{ij}Cij??Fij?的較小者
若是反向弧連接,且流量大于0,則點(diǎn)流量Δ(vj)Δ(v_j)Δ(vj?)取前點(diǎn)流量Δ(vi)Δ(v_i)Δ(vi?)和弧流量FijF_{ij}Fij?的較小者
步驟3:若標(biāo)記到了匯則轉(zhuǎn)步驟4,否則任選一個(gè)剛剛被標(biāo)記的點(diǎn)設(shè)為uuu,轉(zhuǎn)步驟2,若剛剛沒有標(biāo)記任何點(diǎn)則算法結(jié)束。(步驟2由于會(huì)執(zhí)行多次,剛剛表示步驟2最近一次執(zhí)行時(shí)標(biāo)記的點(diǎn),即viv_ivi?的可被標(biāo)記的鄰點(diǎn))
步驟4:從匯開始,依次回溯被標(biāo)記的點(diǎn),并將兩點(diǎn)之間的弧加/減一個(gè)匯流量Δ(t)Δ(t)Δ(t),正向則加,反向則減,回溯到源后,轉(zhuǎn)步驟1。
算法符號(hào)描述:
步驟0: 設(shè)F是從源s到匯t的任意可行流,對(duì)任意<μ,v>=<vi,vj>∈E<μ,v>=<v_i,v_j>∈E<μ,v>=<vi?,vj?>∈E,令Fij=0F_{ij}=0Fij?=0。//從零流開始。
步驟1: 對(duì)源s=v0s=v_0s=v0?標(biāo)記為(s,+,Δ(s)=∞),S={s},U={vj},j=0,1,2,?,n;μ=vi=s。(s,+,Δ(s)=∞),S={s},U={v_j},j=0,1,2,?,n;μ=v_i=s。(s,+,Δ(s)=∞),S={s},U={vj?},j=0,1,2,?,n;μ=vi?=s。(S表示已標(biāo)記的頂點(diǎn)集,U未檢查的頂點(diǎn)集,初始值為全體頂點(diǎn)。)
步驟2: 對(duì)SˉSˉSˉ(S的補(bǔ))中與μ=viμ=v_iμ=vi?的所有鄰點(diǎn)vjv_jvj?,有:
(1) 若<vi,vj>∈E,且Fij<Cij<v_i,v_j>∈E,且F_{ij}<C_{ij}<vi?,vj?>∈E,且Fij?<Cij?,則將vjv_jvj?標(biāo)記為(vi,+,Δ(vj))(v_i,+,Δ(v_j))(vi?,+,Δ(vj?)),其中Δ(vj)=min?{Δ(vi),Cij?Fij},S=S∪vjΔ(v_j)=min?{Δ(v_i),C_{ij}-F_{ij}},S=S∪{v_j}Δ(vj?)=min?{Δ(vi?),Cij??Fij?},S=S∪vj?。
(2) 若<vj,vi>∈E<v_j,v_i>∈E<vj?,vi?>∈E,且Fij>0F_{ij}>0Fij?>0,則將vjv_jvj?標(biāo)記為(vi,?,Δ(vj))(v_i,-,Δ(v_j))(vi?,?,Δ(vj?)),其中Δ(vj)=min?{Δ(vi),Fij},S=S∪vjΔ(v_j)=min?{Δ(v_i),F_{ij}},S=S∪{v_j}Δ(vj?)=min?{Δ(vi?),Fij?},S=S∪vj?。
步驟3: 若vj=t∈Sv_j=t∈Svj?=t∈S,轉(zhuǎn)步驟4,否則vj≠tv_j≠tvj??=t,令U=U?viU=U-{v_i}U=U?vi?,若S∩U=φS∩U=φS∩U=φ,則算法結(jié)束,當(dāng)前流為最大流;否則若S∩U≠φS∩U≠φS∩U?=φ,任選vi∈S∩Uv_i∈S∩Uvi?∈S∩U,轉(zhuǎn)步驟2。(實(shí)際上,S∩U就是步驟2中剛剛被標(biāo)記的點(diǎn))
步驟4: 令z=tz=tz=t。
步驟5: 若zzz的標(biāo)記為(g,+,Δ(z))(g,+,Δ(z))(g,+,Δ(z)),則F(<g,z>)=F(<g,z>)+Δ(z)F(<g,z>)=F(<g,z>)+Δ(z)F(<g,z>)=F(<g,z>)+Δ(z);
若z的標(biāo)記為(g,?,Δ(z))(g,-,Δ(z))(g,?,Δ(z)),則F(<z,g>)=F(<z,g>)?Δ(z)F(<z,g>)=F(<z,g>)-Δ(z)F(<z,g>)=F(<z,g>)?Δ(z)。
步驟6: 若g=sg=sg=s,則取消所有點(diǎn)的標(biāo)號(hào),轉(zhuǎn)步驟1,否則,令z=gz=gz=g,轉(zhuǎn)步驟5。
標(biāo)記的意義:(vi,+,Δ(vj))(v_i,+,Δ(v_j ))(vi?,+,Δ(vj?))表示點(diǎn)viv_ivi?經(jīng)流量為Δ(vj)Δ(v_j)Δ(vj?)的正向弧到達(dá)點(diǎn)vjv_jvj?
(vi,?,Δ(vj))(v_i,-,Δ(v_j ))(vi?,?,Δ(vj?))表示點(diǎn)viv_ivi?經(jīng)流量為Δ(vj)Δ(v_j)Δ(vj?)的反向弧到達(dá)點(diǎn)vjv_jvj?
符號(hào)描述可能不好理解,對(duì)照文字描述理解。
例子:(編輯太麻煩了,從word截的圖)
歡迎討論
總結(jié)
以上是生活随笔為你收集整理的最大流算法 - 标号法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql my.cnf_如何知道mys
- 下一篇: 【离散数学】高级计数技术