(11)圖算法3: 所有節點對最短路徑與最大流問題

所有結點對的最短路徑問題

Floyd算法

  • 前提條件: 可以有負權重邊, 但是不能有負權重的環.
  • 特點: 動態規劃, V^3.
  • 按照動態規劃的步驟:
    • 最優子結構: d[i][j]表示結點vi至結點vj的最短路徑, 而帶上了上標d[i][j]<k>表示允許取用v1~vk情況下結點vi至vj的最短路徑. 我們可以看出這里存在了一個最優子結構, 因為取用1k的最短路徑是在取用1k-1的最短路徑和用上k的最短路徑之間選取的min.
    • 遞歸式: d[i][j]<k> = min{ d[i][j]<k-1>, (d[i][k]<k-1>+d[k][j]<k-1>) }. (常規情況, 當k>=1時)
      或者 = w(i, j); (邊界情況, 當k=0時) //其中i=j時, 應該w(i, i) = 0; 沒有(i, j)邊的時候, 為INF;
    • 自底向上計算:
      • 三個循環, i, j, k. k循環是用來算d[i][j]這個格子的min, 總共是一個二維矩陣, 因此要算O(V^3)時間.
Floyd(W) {  //W[V][V]是二維數組, 存放邊的權重.
let D[V][V] be a new array, and D = W;
for k = 1~V:
    for i = 1~V:
        for j = 1~V:
            D[i][j] = min{ D[i][j], D[i][k]+D[k][j] };
return D;
}

用于稀疏圖的Johnson算法

前提條件: 允許有負權重的環;
特點: 利用G', h(v) = δ(s, v)來為Dijkstra創造無負權重邊的條件;

Johnson(G, w) {
compute G':
    G'.V = G.V ∪ {s};
    G'.E = G.E ∪ {(s, v) for all v ∈ G.V}
    w(s, v) = 0 for all v ∈ G.V
if Bellman-Ford(G', w, s) == FALSE: {
    print "The graph contains negative loop;"
    }
else: {
    for each v ∈ G'.V:
        set h(v) = δ(s, v) from Bellman-Ford
    for each edge(u, v)∈G'.E:
        set w'(u, v) = w(u, v) + h(u) - h(v)    //set all weight to non-negative.
    let D = d[][] be n*n matrix
    for each u∈G.V:
        do Dijkstra(G, w', u)
        for each v∈G.V:
            d[u][v] = δ'(u, v) + h(v) - h(u)
    return D matrix
    }
}

算法時間復雜度分析:

Bellman-Ford已知是O(VE) 因為有V-1輪對所有邊的操作, Dijkstra是O(ElgV)或者O(VlgV+E), 因為extract-min有V次, decrease-key有E次.
本算法主要時間顯然是花在了對所有點進行Dijkstra操作, 顯然總時間是O(VElgV) 或者 O(V^2*lgV+VE).

最大流問題

基本方法

Ford-Fulkerson method

Ford-Fulkerson-Method(G, s, t) 
initiate flow f to 0
while there exists an augmenting path p in residual network Gf:
    augment flow f along p
return f

定理

最大流最小割定理

定理: f是G的一個最大流
= 殘存網絡Gf不再包含任何增廣路徑
= |f| = c(S, T) , 其中(S, T)是流網絡G的某個切割;

  • 說明: 第三行某個切割可以是任意一個切割, 因為流網絡具有切割流量相等的性質.

基本款算法

Ford Fulkerson Basic

/* 基本的FF最大流算法 */
// 約定: (u,v).f代表邊(u,v)上當前的流量;
// Cf(p)代表path p整條最短路徑所允許的殘余網絡最大流量
// Cf(u, v)代表(u, v)邊上的殘余網絡流量, 本質上是一種潛能(potential)

Ford-Fulkerson(G, s, t)
for each edge (u, v)∈G.E:
    (u, v).f = 0
while there exists an augmenting path p in residual network Gf:
    Cf(p) = min{Cf(u, v): (u,v) is in path p}
    for each edge(u, v) in path p:
        if (u, v) ∈ G.E:
            (u, v).f = (u, v).f + Cf(p)
        else:
            (v, u).f = (v, u).f - Cf(p)
  • 找augmenting path的方法: 用BFS對殘存網絡Gf進行搜索, 找到一條path;

時間復雜度分析: 算法初始化花費Θ(E), 而while循環的條件如果是用廣度優先搜索, 每次要花O(V+E) = O(E), 而循環內求殘余容量Cf(p)操作最多有|V-1|條邊構成一條最短路徑, 因此是O(V), 而接下去對path上所有邊的操作, 也是O(V)的. 因為V<=E, 因此單次while循環消耗O(E), 而由我們的關鍵邊上限定理, 可以知道最多有VE條關鍵邊, 每條path至少一條關鍵邊, 因此有O(VE)條path, 因此總時間復雜度為O(V·E^2).

算法的正確性:
為什么使用BFS不斷找出最短邊(所有邊長度設定為1), 可以實現把while循環控制在VE次呢?

先介紹一個基礎: δ(s, v)單調遞增定理

從源點s到非終點t的某個點v的最短距離總是在遞增, 即δ'(s, v) >= δ(s, v). 證明:
反證法: 假設某輪增加流量之后, 存在δ'(s, v)<δ(s, v). 這時, 我們找處于邊界v點, 從s到v點的最短路徑上, v前面一個點u滿足δ'(s, u)=δ(s, u). 已知δ(s, v) <= δ(s, u)+1, δ'(s, u)<=δ'(s, v)+1, δ'(s, v)<=δ(s, v)-1, 那么δ(s, u)+1 >= δ'(s, v)-1, 也就是δ(s, u) >= δ'(s, v)-2與δ'(s, u)<=δ'(s, v)+1是矛盾的.

更加直覺一些地, 隨著算法運行, 有些邊可能由于流量被加到滿導致在殘存網絡中消失:

  • 如果消失的邊在s~v的最短路徑上, 顯然δ(s, v)將不得不繞別的路, 因而會增加;
  • 如果消失的邊不在s~v的最短路徑上, 那么也不會影響到δ(s, v).
  • 要認識到, 只有當圖中出現了連接之前從未被連接過的兩點的新邊, 才存在使δ(s, v)下降的可能性.

關鍵邊O(VE)上界的推導:

(u, v)如果第一次被當做最短路徑p的關鍵邊話, 會從Gf殘存網絡圖上消失, 此時有δ(s, v) = δ(s, u)+1;
其如果想再次成為關鍵邊, 至少要滿足必要條件 (v, u).f 被增加過, 且(u, v)再次被當成最短路徑的一部分. (v, u).f要被增加過的話, 那么(v, u)邊得被納入過最短路徑, 那么(v, u)滿足了δ'(s, u) = δ'(s, v)+1;
已知定理26.7說殘存網絡中δ(s, v)隨著每次流量的遞增操作而單調遞增 ==> δ'(s, v) >= δ'(s, v), 所以δ'(s, u) = δ'(s, v)+1>=δ(s, v)+1 = δ(s, u)+2.
因此我們得到了一個性質: 當(u, v)邊成為一次關鍵邊后, δ(s, u) = δ(s, u)+2, 即關鍵邊遞增, 遞增的步長為2.
已知從起點s到終點t最短路徑最長不能超過V-1, u除了不可能是終點t外, 可以是任何點, 因此(u, v)最多可以當關鍵邊(V-2)/2次, 從而每條邊只能當關鍵邊次數 = O(V/2) = O(V), 那么對所有邊來說, 最多只能有O(VE)次關鍵邊的出現.
延伸: O(VE)條關鍵邊, 而每個增廣路徑至少有一條關鍵邊, 因此O(VE)條增廣路徑.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容