出處:http://www.cnblogs.com/bigmonkey
本文以學習、研究和分享爲主,如需轉載,請聯繫本人,標明做者和出處,非商業用途!
掃描二維碼關注公衆號「我是8位的」
又是一個晴朗的假日,居住在A城市的上班族打算到附近的B城市看看天然風光。當你們將車開到高速上時,又一次遇到了毫無懸念的擁堵,兩個城市間的收費站成了擁堵的重災區。下圖展現了兩個城市間高速公路的網絡模型。算法
圖1網絡
每一個頂點表明一個收費站,v1是A城市的出口,v6是B城市的入口,邊的權重表明高速公路的運力c(v1)~c(v6) 表明每一個收費站的容量,該容量和高速公路的運力單位相同。爲了緩解擁堵,兩個城市向每一個收費站加派了交警,以便引導司機走相對快速的路線。交警該以怎樣的方案調度車輛呢?post
交通流正好能夠規約成網絡流模型,但因爲加入了頂點的容量,問題彷佛也變得更加複雜。回顧流網絡的定義,G=(V,E,s,t,C)並無包括頂點的容量,想要將圖1規約成網絡流模型,須要先想辦法去掉頂點的容量。學習
咱們的解決方案是用邊代替頂點,具體作法是對每一個有容量頂點v,都添加一個新的頂點v’,鏈接vv’,使c(v→v’)=c(v),並將v的流出邊轉移到v’上:spa
圖2code
圖2已經將帶有容量的頂點轉換成了一個普通的st-網,只要更改一下輸入,就可使用最大流的相關算法找出車輛調度方案。程序中將頂點v的值乘以10做爲v’。blog
1 import network_flow as nf 2 3 V = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] 4 E = [nf.Edge(0, 1, 18), nf.Edge(0, 2, 18), nf.Edge(0, 3, 18), nf.Edge(1, 4, 9), nf.Edge(1, 5, 9), 5 nf.Edge(2, 5, 9), nf.Edge(2, 6, 9), nf.Edge(3, 6, 9), nf.Edge(3, 7, 9), nf.Edge(4, 8, 3), 6 nf.Edge(4, 9, 12), nf.Edge(5, 9, 6), nf.Edge(5, 10, 14), nf.Edge(6, 10, 7), nf.Edge(6, 11, 5), 7 nf.Edge(7, 11, 10), nf.Edge(7, 12, 12), nf.Edge(8, 13, 8), nf.Edge(9, 13, 8), nf.Edge(10, 13, 8), 8 nf.Edge(11, 13, 8), nf.Edge(12, 13, 8)] 9 s, t = 0, 13 10 G = nf.Network(V, E, s, t) 11 ford_fullkerson = nf.FordFulkerson(G) 12 ford_fullkerson.start() 13 ford_fullkerson.display()
能夠看到,最大流除了受邊的容量影響外,還受到節點容量的影響。get
第二次世界大戰期間,英國皇家空軍從淪陷國徵募了大量外籍飛行員。在執行飛行任務時,由皇家空軍派出的每一架飛機都須要配備在航行技能和語言上能互相配合的兩名飛行員,其中一名是英國飛行員,另外一名是外籍飛行員,每一名英國飛行員均可以與若干名外籍飛行員很好地配合。在一次大規模戰略任務中,如何匹配飛行員才能使皇家空軍一次能派出最多的飛機?class
假設有m個英國飛行員和n個外籍飛行員,一個不加思索的答案是能夠派出min(m, n)架飛機。事實並不是如此,能夠用圖3輕易地反駁。效率
圖3
a1~a4和b1~b5表示有4名英國飛行員和5名外籍飛行員,其中可以匹配a1、a3、a4的只有b2和b5,所以沒法派出4架飛機。
圖3的模型稱爲二部圖,也叫二分圖。二部圖的頂點分屬於兩個集合A和B,對於圖中的每無向條邊vw來講,都有v屬於A且w屬於B。基於二部圖模型的匹配方案稱爲二部匹配。
一種找到匹配的方案是使用窮舉搜索,可是這種方案太太低效,找出最佳匹配可能要搜索全部的匹配方案。假設A集合中有m個頂點,每一個頂點都可以發出k條邊,那麼窮舉法在極端狀況下須要執行km次才能得出結果,這種指數爆炸級的效率顯然是不可接受的。
網絡流能夠有效地處理二部匹配,再此基礎上加上超級源點和超級匯點,並令每條邊的容量爲1,這就把一個二部圖變成了一個流網絡:
因爲每條邊的容量都是1,所以網絡流老是可以提供一個合法的匹配,使每一個內部頂點至多隻有一個單位的流,這至關於A中的頂點至多隻能和B中的一個頂點相匹配。如今能夠很容易地找到飛行員的匹配方案了。
1 import network_flow as nf 2 3 V_EN = ['a1', 'a2', 'a3', 'a4'] 4 V_FN = ['b1', 'b2', 'b3', 'b4', 'b5'] 5 s, t = 's', 't' 6 V = [s] + V_EN + V_FN + [t] 7 E = [nf.Edge(s, pilot, 1) for pilot in V_EN] + [nf.Edge(pilot,t, 1) for pilot in V_FN] 8 E += [nf.Edge('a1', 'b2', 1), nf.Edge('a1', 'b5', 1), nf.Edge('a2', 'b1', 1), nf.Edge('a2', 'b3', 1), 9 nf.Edge('a2', 'b5', 1), nf.Edge('a3', 'b2', 1), nf.Edge('a4', 'b2', 1), nf.Edge('a4', 'b5', 1)] 10 11 class FordFulkerson_Pilot(nf.FordFulkerson): 12 def display(self): 13 print('最大網絡流 = ', self.max_flow) 14 print('%-10s%-8s%-8s' % ('邊', '容量', '流')) 15 for e in self.G.E: 16 if e.flow == 1: 17 print('%-10s%-10d%-8s' % (e, e.cap, str(e.flow) + '*')) 18 19 G = nf.Network(V, E, s, t) 20 ford_fullkerson = FordFulkerson_Pilot(G) 21 ford_fullkerson.start() 22 ford_fullkerson.display()
做者:我是8位的