日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

网络流(3)——找到最小st-剪切

發布時間:2024/9/5 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络流(3)——找到最小st-剪切 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  在大規模戰爭中,后勤補給是重中之重,為了盡最大可能滿足前線的物資消耗,后勤部隊必然要充分利用每條運輸網。與此同時,交戰雙方也想要以最小的代價切斷敵軍的補給,從而使敵軍處于孤立無援的境地。在古今中外的各種重大戰役中,上演了一幕幕補給線上的攻防戰。

甲軍的運輸路線

  假設甲、乙兩軍正在交戰,圖8.17是甲軍的補給運輸網,其中t是甲軍的前沿陣地,s是后勤大營,每條邊是一條公路,邊上的數字代表公路的寬度。

  如果甲軍想要盡最大努力供應前線的消耗,應該怎樣設計運輸路線?

  這個問題很容易規約成網絡流模型,使用下面的代碼可以直接計算出結果。

1 import network_flow as nf 2 3 V = [0, 1, 2, 3, 4, 5, 6, 7, 8] 4 E = [nf.Edge(0, 1, 15), nf.Edge(0, 2, 15), nf.Edge(0, 3, 15), nf.Edge(1, 4, 2), nf.Edge(2, 4, 3), 5 nf.Edge(2, 5, 2), nf.Edge(3, 5, 4), nf.Edge(4, 5, 2), nf.Edge(4, 6, 2), nf.Edge(5, 6, 4), 6 nf.Edge(5, 7, 3), nf.Edge(6, 8, 15), nf.Edge(7, 8, 15)] 7 s, t = 0, 8 8 G = nf.Network(V, E, s, t) 9 ford_fullkerson = nf.FordFulkerson(G) 10 ford_fullkerson.start() 11 ford_fullkerson.display() 12 X, Y, st_cut = ford_fullkerson.min_st_cut() 13 ford_fullkerson.display_st_cut(X, Y, st_cut)

  (network_flow參考上一章的相關代碼)運行結果對應的網絡流:

乙軍的轟炸目標

  甲軍想要充分利用每條公路,乙軍的目的正好相反,是破壞公路網,使乙軍的戰斗部隊處于孤立無援的境地。乙軍打算組織一次針對甲軍補給線的戰略轟炸,由于甲軍在每個節點都部署了大量防空武器,因此需要繞過節點,直接轟炸防御薄弱的公路。假設炸掉容量為1的公路需要n顆炸彈,破壞的公路容量和投擲的炸彈數成正比,怎樣設計轟炸目標才能以最小的代價完全破壞敵軍的補給線?

  一個方案是炸毀直接通向匯點的公路,但由于連接匯點的兩條公路太寬,完全破壞需要30n的炸彈,這顯然不是最小代價。如果換個地點,假設轟炸的是v5→v7,那么只需要3n的炸彈就可以使寬敞的v7→t淪為擺設。為了設計這種轟炸方案,需要理解最小st-剪切的概念。

8.3.3 最小st-剪切

  設計成本最低的轟炸方案是我們的目標,直接尋找起來比較困難,幸而這個目標與網絡的最小剪切有密切關系。

  一個流網絡的頂點可以劃分成兩個不相交的集合X和Y,源點s和匯點t分屬于這兩個集合,連接X和Y的邊稱為這個流網絡的st-剪切(st-cut,也稱為截、割或切割)。我們用淺色圓圈表示包含源點的集合X,深色圓圈表示包含匯點的集合Y,這樣就很容易看出一個流網絡的st-剪切:

  既然st-剪切是邊的集合,那么集合中邊的容量之和就是st-剪切的容量。一個流網絡有很多種不同的st-剪切,其中容量最小的一個就是最小st-剪切。

  st-剪切包含了所有源點到匯點的通道,一個顯而易見的結論是:st-剪切的流值等于這個網絡流的值。更進一步,任何網絡流的值都不會超過st-剪切的容量,這也意味著st-剪切代表著流網絡的瓶頸,最小st-剪切的容量不會小于最大流的值,這個定理稱為最大流-最小剪切定理。該定理也可以反過來表述:網絡流的值最大不會大于任意一個給定的st-剪切的容量。當X只包含源點或Y只包含匯點時,最大流-最小剪切定理最為直觀。

  最小st-剪切代表補給線上最難走或最重要的路段,只要破壞這些路段,就能以最小的代價掐斷敵軍的補給,即使只破壞了一部分,也能有效降低敵軍的補給能力。既然最小st-剪切和最大流存在關聯關系,我們就可以在尋找最大流時順帶找出最小st-剪切,這仍然需要使用殘存網。在殘存網中,將源點和從源點出發可以到達的頂點看作集合X,剩下的頂點看作集合Y,對于邊v→w,如果滿足v屬于X,w屬于Y,那么v→w就是最小st-剪切中的一條邊。

  以下圖為例,在殘存網中源點能夠到達的頂點只有v3,原網絡的最小st-剪切是:

  可以根據這種思路在FordFulkerson中添加尋找最小st-剪切的實現。

1 class FordFulkerson(): 2 def __init__(self, G:Network): 3 self.G = G 4 self.max_flow = 0 # 最大流 5 …… (省略部分參考上一章的相關代碼) 6 def min_st_cut(self): 7 ''' 找到最小st-剪切 ''' 8 X = [self.G.s] # st-剪切的X集合 9 stack = [self.G.s] 10 while len(stack) > 0: 11 v = stack.pop() 12 for e in self.G.edges_from(v): # 所有從v頂點流出的邊 13 if e.w != self.G.t and e.w not in X and e.residual_cap_to(e.w) > 0: 14 X.append(e.w) 15 stack.append(e.w) 16 Y = list(set(self.G.V) - set(X)) # st-剪切的X集合 17 st_cut = [e for e in self.G.E if e.v in X and e.w in Y] # 連接X和Y的邊 18 return X, Y, st_cut 19 20 def display_st_cut(self, X, Y, st_cut): 21 print('X={0}, Y={1}'.format(X, Y)) 22 print('st-cut={}'.format([str(e) for e in st_cut]))

  min_st_cut使用深度優先搜索尋找最小st-剪切。由于這種方法需要借助殘存網,因此在使用min_st_cut前需要首先執行一次計算最大流的操作。現在可以計算出乙軍的轟炸目標了:

姜子牙的押糧官

  在《封神演義》中,姜子牙經過金臺拜將之后,擔任“掃蕩成湯天寶大元帥”一職,代武王伐紂。率領六十萬西岐大軍浩浩蕩蕩,東進朝歌。所謂“三軍未動,糧草先行”,在臨行前,姜子牙任命了四個先鋒官的同時,又任命了楊戩、土行孫、鄭倫三個押糧官。

  押糧前必先征糧,單從一個地方征糧恐怕不足以支持一場滅國戰爭,假設下圖是西岐的糧道。

  邊的容量代表糧道的運力,楊戩、土行孫、鄭倫分別從三v1、v2、v3個征糧地同時出發,將糧草運往唯一的前沿陣地t,由于運糧過程中十分安全,所以三人可以在每個節點處合兵或分兵,怎樣行進才能使糧道發揮出最大運力呢?

多個源點與多個匯點

  問題可以規約成典型的最大流問題,但與之前介紹的st-網絡不同,糧道圖中有多個源點(或者說沒有源點),如此一來將會對最大流的相關算法造成影響,怎么辦呢?

  其實很簡單,在三個源點前再加入一個超級源點,這樣一來v1、v2、v3就變成了普通的節點,它們也符合守恒定律,原網絡也轉換成了st-網:

  與此類似,也可以通過建立一個超級匯點來處理多個匯點的情況。

糧道的最大運力

  有了超級節點后,只要把初始數據輸入交給計算機就可以了。

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), 5 nf.Edge(1, 5, 9), nf.Edge(2, 5, 9), nf.Edge(2, 6, 9), nf.Edge(3, 6, 9), 6 nf.Edge(3, 7, 9), nf.Edge(4, 8, 3), nf.Edge(4, 9, 12), nf.Edge(5, 9, 6), 7 nf.Edge(5, 10, 14), nf.Edge(6, 10, 7), nf.Edge(6, 11, 5), nf.Edge(7, 11, 10), 8 nf.Edge(7, 12, 12), nf.Edge(8, 13, 8), nf.Edge(9, 13, 8), nf.Edge(10, 13, 8), 9 nf.Edge(11, 13, 8), nf.Edge(12, 13, 8)] 10 s, t = 0, 13 11 G = nf.Network(V, E, s, t) 12 ford_fullkerson = nf.FordFulkerson(G) 13 ford_fullkerson.start() 14 ford_fullkerson.display()

  最大流是33,下圖是根據程序運行結果映射的網絡流。

  最大流是確定的,但押糧路線并不是唯一的,最大流算法和邊的輸入順序都會對它產生影響。對于增廣路徑最大流算法來說,尋找增廣路徑的算法也會影響最終的押糧路線。

  


  ?作者:我是8位的

  出處:http://www.cnblogs.com/bigmonkey

  本文以學習、研究和分享為主,如需轉載,請聯系本人,標明作者和出處,非商業用途!?

  掃描二維碼關注公眾號“我是8位的”

轉載于:https://www.cnblogs.com/bigmonkey/p/11010891.html

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的网络流(3)——找到最小st-剪切的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。