一、引言
如同我們可以把乙個實際的道路地圖抽象成乙個有向圖來計算兩點之間的最短路徑,我們也可以將乙個有向圖看作乙個流網路來解決另一型別的問題。流網路比較適合用來模擬液體流經管道、電流在電路網路中的運動、資訊網路中資訊的傳遞等等類似的過程。
二、網路流和最大流問題
參看下圖,給定乙個有向圖g=(v,e),把圖中的邊看作管道,每條邊上有乙個權值,表示該管道的流量上限。給定源點s和匯點t,現在假設在s處有乙個水源,t處有乙個蓄水池,問從s到t的最大水流量是多少,類似於這類的問題都可歸結為網路流問題。
在流網路中,每條有向邊可以被看導管。每根導管有乙個固定的容量,代表物質流經這個導管的最大速率,例如乙個管道每小時最多能流過200加侖液體或者一根電線最多能承載20安培的電流。流網路中的頂點可以看作是導管的連線處。除了源點和匯點之外,物質流進每個點的速率必須等於流出這個點的速率。如果我們把研究的物質特化為電流,這種「流的保持」屬性就好像電路中的基爾霍夫電流定律一樣。
下面我們用數學語言來進行相關概念的定義:
設g=(v,e)是乙個流網路,設c(u, v)>=0 表示從u到v的管道的流量上限。設s為源,t為匯。g的流是乙個函式f: v×v →r,且滿足下面三個特徵:
1.容量限制:對於所有的 u,v ∈ v, 要求f(u, v) <= c(u, v)
2.斜對稱性:對於所有的 u,v ∈ v, 要求f(u, v) = - f(v, u)
3.流的保持:對於所有的 u ∈ v - ,要求:∑ f(u, v) = 0(v∈v)
f(u,v)稱為從結點u到v的網路流,它可以為正也可以為負。流 f 的值定義為:|f| = ∑ f(s, v)(v∈v)即從源出發的所有流的總和。
最大流問題就是找出給定流網路的最大流。網路流問題可以歸結為一類特殊的線性規劃問題。
三、解決最大流問題常用演算法一覽
解決最大流問題的常用到ford-fulkerson方法,之所以稱其方法而不是演算法,是因為在這種思想下包含著若干種時間複雜度不同的實現,其中較多地是使用edmonds-karp演算法。與此相對,push-relabel演算法採用了與ford-fulkerson方法完全不同的思考角度,降低了漸進意義下的時間複雜度。而relabel-to-front演算法則是對push-relabel演算法的改良和精煉,效率更佳。
關於這三種常用演算法的時間複雜度可見下表:(其中v表示圖的頂點數,e表示邊數)
演算法名稱
edmonds-karp演算法
一般性的push-relabel演算法
relabel-to-front演算法
時間複雜度
o(v*e^2)
o(v^2*e)
o(v^3)
可以看出,當給定的有向圖比較稀疏時,三種演算法的效率不會相差太多,但當網路稠密時,relabel-to-front演算法在效率上有著明顯的優勢。
四、基於ford-fulkerson方法的edmonds-karp實現
一般的ford-fulkerson方法具有迭代性質,我們把頂點u和v之間的流記作f(u,v)。那麼在最開始,我們對所有的u,v∈v置f(u,v)=0。在每次的迭代過程中,通過找到一條增加路徑來使|f|增加。在這裡,我們可以簡單地認為所謂的「增加路徑」就是一條可以傳送比當前更多流的從源點s到匯點t的路徑,一旦找到了這樣的路徑,我們就可以得到乙個比原流數值更大的新流。重複這個過程,直到不存在增加路徑為止,這就是ford-fulkerson方法的主要過程,可以用偽碼表示如下:
ford-fulkerson-method(g,s,t)
將流f初始化為0
while 存在一條增加路徑p
do 順沿p增加f
return f
實現ford-fulkerson的時間複雜度主要取決於如何尋找增加路徑p。edmonds-karp實現正是通過採用了廣度優先的搜尋策略得以使其複雜度達到o(v*e^2)。
由於這種演算法的效率不很理想,我們在此不多著墨,而主要介紹下述push-relabel演算法的思想。
五、一般性的push-relabel演算法
很多漸進意義下最優的演算法都是採用了push-relabel演算法的思想,而且很多其他的相關問題,比如最小費用流問題,也可以用這種方法很好的解決。首先介紹的是一般性的push-relabel演算法。
不同於ford-fulkerson方法在殘留網路中尋找增加路徑的方式,push-relabel演算法在執行的過程中只關注某乙個頂點以及它的相鄰頂點,在這個過程中,它並不像ford-fulkerson方法保持著「流的保持」性質,而是以乙個「先流」進行運作。這個先流同樣是乙個 v×v →r的函式,滿足容量限制和斜對稱性,同時,它對所有的u∈v-滿足f(v,u)>=0。我們記e(u)=f(v,u)。如果e(u)>0我們就說頂點u溢位。
為了步入正題,我們還需要介紹push-relabel演算法引入的乙個額外的高度函式。設g=(v,e)是乙個流網路,源點是s,匯點是t,f是g中的乙個先流。如果函式h:v→n滿足h(s)=|v|,h(t)=0,而且對殘留網路中所有的邊(u,v)有h(u)<=h(v)+1,那麼稱h是乙個高度函式。
正如其名稱一樣,push-relabel演算法有兩個基本操作:push和relabel。一般性的push-relabel演算法就是通過往復執行這兩種操作完成的:
generic-push-relabel(g)
先流初始化
while 存在可以執行的push或relabel操作
選擇乙個可以執行的push或relabel操作執行
下面具體介紹一下這兩個基本操作。
push(u,v)
可以執行的時機:頂點u溢位,u、v之間的殘留容量cf(u,v)為正,且h[u]=h[v]+1
動作描述:將df(u,v)=min(e[u],cf(u,v))個單位的流從u壓向v
具體步驟:
df(u,v)=min(e[u],cf(u,v))
f[u,v]=f[u,v]+df(u,v)
f[v,u]=-f[u,v]
e[u]=e[u]-df[u,v]
e[v]=e[v]+df[u,v]
relabel(u)
可以執行的時機:u溢位,且對所有的殘留網路中的邊(u,v),有h[u]<=h[v]
動作描述:增加u的高度
具體步驟:
h[u]=1+min
通過證明,在一般性的push-relabel演算法執行過程中,relabel操作的執行次數小於2|v|^2,push操作的執行次數小於2|v||e|+4|v|^3+4|e||v|^2,而每個relabel操作的耗時在o(v)級,每個push的耗時在o(1)級,選擇乙個可以執行的操作也可以在o(1)內完成,因此,存在具體的實現使得一般性的push-relabel演算法時間複雜度達到o(v^2*e)。
六、relabel-to-front演算法
通過引入鄰接表和許可邊的概念,relabel-to-front演算法在push-relabel演算法的基礎上進一步提公升了效率,使時間複雜度可以達到o(v^3),但是該演算法的步驟和證明的過程比較繁瑣,在這裡就略去了,有興趣的讀者可以參考《演算法導論》。
七、二部圖的最大匹配與網路最大流的關係
有一定離散基礎的讀者應當對二部圖的最大匹配不陌生,但它和網路流之間有什麼具體的聯絡呢,請看下圖:
是的,如果我們設二部圖兩部分的點集分別為l與r,現在新增源點s和匯點t,對所有的v∈l新增有向邊(s,v),再對所有的v∈r新增有向邊(v,t),再將原二部圖中所有的無向邊改為自l中的點指向r中的點的有向邊,就構造了乙個流網路。如果這個網路中每條邊的容量限制都設為1,那麼它的最大流數值就等於二部圖的匹配數,而且這個最大流和二部圖中的最大匹配是一一對應的。
Docker相關概念及要點
1.基本概念 docker 的容器通過 linux 的命名空間完成了與宿主機程序的網路隔離。docker 為我們提供了四種不同的網路模式,host container none 和 bridge 模式。docker 預設的網路設定模式 網橋模式。我們通過 linux 的命名空間為新建立的程序隔離了檔...
About Hive相關概念及HiveQL操作
root bdpdatanode01 hive e select count 1 from prod bdw.dwd calendar root bdpdatanode01 hive s e select count 1 from prod bdw.dwd calendar 1 託管表和外部表 2 ...
nbd 相關概念及操作
周五 3月6號 筆者發現有台物理機上掛載了乙個並非常用的nbd裝置,估計是之前人做的測試留下來的,決定解除安裝它,順帶了解了下nbd的裝置資訊。什麼是nbd 全稱是network block device,類似於nfs,遠端裝置可以掛載,只不過掛載的不再是檔案系統,而是塊裝置。nbd一般分為clie...