ISAP網路流演算法

來源:互聯網
上載者:User

標籤:需要   因此   優先   head   情況下   相同   編號   開始   接受   

  ISAP全稱Improved Shortest Augmenting Path,意指在SAP演算法進行最佳化。SAP即Edmonds-Karp演算法,其具體思路是通過不斷向殘存網路推送流量來計算整個網路的最大流。閱讀本文要求掌握網路流的基礎概念,不懂的出門左拐演算法導論。ISAP的時間複雜度與EK演算法一致,而EK演算法的時間複雜度為min(O(E|f|),O(VE^2)),其中O(E|f|)部分是因為其是在FORD-FULKERSON演算法上的改進。EK演算法在FF演算法的基礎上將隨意取增廣路徑替換為取最短增廣路徑,而ISAP在EK演算法的基礎上剔除了除了第一次外的後續廣度優先搜尋尋找最短路徑的部分。下面對ISAP演算法進行說明。

  先說明一些名詞,稱殘存網路中容量非0的邊為有效邊。

  我們首先在EK演算法的基礎上,為每個頂點添加新的屬性d,表示其到匯點t的最短路徑(路徑只能包含有效邊),這個最短路徑是基於殘存網路的,而非原圖,因此d屬性會隨著流的推送導致殘存網路的變更而變更。顯然要維護這樣一個屬性d,每次在推送流後,都需要基於新形成的殘存網路重新執行廣度優先搜尋演算法,以計算每個頂點正確的d屬性,這樣不就與EK演算法完全一樣了嗎?是的,因此為了避免每次流推送都必須重新計算最短路徑,我們需要修改d的定義,d表示頂點到t的距離的某個下界。為了說明這樣定義之後就不用再每次重新執行廣度優先搜尋演算法計算d,只需要說明每次向殘存網路推送流,只會導致每個頂點到t的距離非嚴格遞增:

  證明:假設我們向圖G沿最短路徑推送流,並形成新圖G‘。我們記R(a,b)表示原圖中從點a到點b的最短距離,記R‘(a,b)表示在新圖(殘存網路)中a到b的最短距離。我們所要證明的就是對於任意點x都有R(x,t)<=R‘(x,t)。假設存在點x,滿足R(x,t)>R‘(x,t),顯然x到t的最短路徑之中必然包含由於流推送而新增的邊,假設(v,u)是圖G‘中x到t中距離點x最近的新增邊,而(u,v)是處於G中最短增廣路徑上。這樣我們就可以把G‘中的x到t的最短路徑寫作x,...,v,u,...,t,顯然R‘(x,v)=R(x,v),因為其中不含新增邊和刪除邊(即與G上的最短增廣路徑無交集)。由於R‘(x,t)<R(x,t)可得R‘(v,t)<R(v,t),從而有R‘(u,t)<R(u,t),因此由前面的說明可知存在增廣路徑的邊(q,w),使得(w,q)存在於R‘(u,t)代表的最短路徑中。利用同樣的思路證明下去我們可以得到無窮多的增廣路徑上的邊出現在了R‘(x,t)對應的路徑之中,而由於一條最短路徑是不可能包含重複邊,且所有不同邊的總數最多隻有2*|E|條(正向邊以及逆向邊),因此這與R‘(x,t)是最短路徑這一性質相悖,故假設不成立,因此R‘(x,t)>=R(x,t)。

  繼續說明流程的執行。由於d是描述一個頂點距離t的下界,因此當一個頂點的屬性d超過|V|時,這個頂點將永遠無法推送流到t(最短路徑不含相同頂點的簡單應用)。而我們可以以源點s的屬性d是否超過|V|來作為結束推送的條件。具體流程是我們迴圈推送,每次都從s開始向其餘所有與s相鄰且d屬性為s.d-1的頂點推送無窮的流。我們期望這樣的流推送成功若且唯若增廣路徑上的頂點序列的d屬性為s.d,s.d-1,...,1,0,否則推送就不應該成功。顯然在推送成功的情況下,由於d是距離下界,因此推送路徑一定是最短的增廣路徑。而所謂的推送失敗是指抵達一個頂點x(非t),所有鄰接的可抵達頂點(指存在有效邊串連)的距離都不等於x-1,這意味著附近的所有頂點到t的距離都由於前面對流的推送而增大了,因此我們也應該對x的距離進行增大(因為一個頂點距離t的最短距離應該是其與可以通過有效邊串連的所有頂點到t的最短距離的最小值+1),由於周邊的所有頂點的d屬性均>=x.d,因此我們將x.d賦值為x.d+1也是合適的,不會違背我們對d的定義,在我們修改了d的值之後,顯然這與我們期望的可推送的增廣路徑已經不相符了,因為d屬性為x.d+1的頂點出現了兩次,因此我們宣告失敗回到之前的頂點。而當我們推送成功且x是方才推送的增廣路徑上的某個頂點,且此時從前面頂點傳來的流還足夠支援下次推送,那麼我們可以繼續尋找其滿足d屬性為x.d-1的後繼頂點,繼續推送(這也是ISAP的最佳化之一)。

  先說明程式會正確停止。由於推送成功就意味著存在增廣路徑(而且是符合嚴苛條件的最短增廣路徑),此時顯然還可以繼續通過向增廣路徑推送流來獲得最大流。當我們發現不存在增廣路徑時,即s向周邊推送失敗,我們會不斷增大s.d屬性,而當s.d>|V|時,我們就結束推送,此時程式正確結束。

  時間複雜度與EK基本一致,只是將其中原本每次成功推送後執行廣度優先搜尋去掉,取而代之的是增加了推送失敗情況下對頂點d屬性的增大。由於一個頂點d屬性不會超過|V|,因此我們可以保證每個頂點d屬性最多增大|V|次,而總共有|V|個頂點,因此失敗處理次數不會超過|V|^2。同時由於我們每次推送成功時也會遍曆大量的不同邊和不同頂點,這個流程在最糟糕的情況下的時間複雜度為O(|V|+|E|),與廣度優先搜尋演算法一致,因此演算法上界應該為O(VE^2+V^2)=O(VE^2),與EK演算法一致。

  ISAP有一個通用的GAP最佳化就是我們將擁有不同d屬性值的頂點進行分組,以d屬性值作為編號。當我們修正一個頂點p的d屬性值(推送失敗時),我們可以通過判斷p.d這一組元素是否只有一個,當只有一個時,意味著我們再修改p.d為p.d+1後,p.d這一組將會為空白,這是一個好訊息,因為後面所有從s發出的推送請求都會由於沒有p.d組的頂點可以接受請求而失敗,因此我們可以斷定此時殘存網路中的流即是最大流,我們可以通過提前將s.d修改為|V|來跳過後面一系列的失敗處理,從而最佳化效能。

  下面給出代碼:

  

bfs(t) //從t開始進行廣度優先搜尋,如果頂點v到t無路徑,則v.d=-1
  for v in V
    v.d=-1    t.d = 0 que = empty-queue que.enque(t) while(!que.isEmpty()) head = que.deque() group[head.d]+=1 for edge in head.edgeList if(edge.isNegative)//只允許沿著有效邊的反向邊移動 if(edge.dst.d == -1) edge.dst.d = head.d + 1 que.enque(edge.dst)sendFlow(node, flowLimit) //通過頂點node向周圍最多推送flowLimit單位的流,如果推送量為0,則表示推送失敗 total = 0 for edge in node.edgeList if(edge.capacity > edge.flow && edge.dst.d == node.d - 1) //發現合格有效邊 actually = sendFlow(edge.dst, min(flowLimit, edge.capacity - edge.flow) flowLimit -= actually total += actually
       if(flowLimit == 0)
         break if(total == 0) //如果發送失敗 group[node.d]-=1 if(group[node.d] == 0) //發現斷層 s.d = |V| node.d+=1 group[node.d]+=1 return totalisap(s, t) bfs(t) if(s.d == -1)//如果從s到t不存在路徑 return 0 sum = 0 while(s.d < |V|) sum += sendFlow(s, INF)
   return sum

 

ISAP網路流演算法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.