1. 程式人生 > >如何計算圖的最短路徑?

如何計算圖的最短路徑?

演算法導論(MIT 6.006 第15講 第16講 第17講)

最短路徑的定義是什麼?

最短路徑即擁有最小權重的路徑p;
路徑定義: p=< v 0 , v 0 ,…,

v k >, 其中當 0 i < k 時,有 (
v i
, v i + 1 )
E;
路徑的權重:w(p)= Σ i = 0 k 1 w ( v i , v i + 1 ) ;

加上權重的數學表示方式

  1. 邊存在權重的圖:G(V,E,W) ,W是一個函式,作用於邊,生成一個實數,即W(E)->R
  2. 頂點到自身的路徑:( V 0 )表示從( V 0 )到( V 0 )的路徑,權重是0
  3. 兩個頂點之間的最短路徑:
    δ ( u , v ) = { u , v m i n { w ( p ) } u , v

E與V的關係 E=O( V 2 )。對於有向圖來講,假設有兩個頂點,v1,v2,他們之間只有4種連線情況,依次類推

為什麼會有負的權重?

比如社交網路上的喜歡可以看做是正的權重,比喜歡可以看做是負的權重

負權重的邊帶來什麼問題?

如果存在一個帶有負權重的邊,那麼每經過一個迴圈,會減少原有的權重值,這樣造成的現象是可以得到任何可以得到的權重值。比如路徑p=

最短路徑演算法的一般思路是什麼?

d(v) 表示從源點s到當前節點v的路徑權重 , π [ v ] 表示當前最好的路徑上,v的前一個節點 ,通過這種方式就能重構整個最短路徑

針對沒有負權重的環
1. 初始化 d[v] = , π [ u ] =NIL,d[s]=0
2. 通過某種方式選擇邊(u,v),執行Relax操作,去更新源點到選擇的頂點的當前路徑值,以及選擇頂點的前一個節點

Relax(u,v,w):
    select edge(u,v):
        if d[v]>d[u]+w(u,v):
            d[v]=d[u]+w(u,v)
            PI[v]=u
    until all edges have d[v] <= d[u]+w(u,v)

relax操作的過程中會不會產生一個一個比 δ (s,v)還要小的值?

通過歸納法,假設有 d[u] δ (s,u)。已知的是 δ ( s , v ) 表示s到v的最短路徑,那麼任意一個到v的頂點u和源點s到u的最短路徑必定大於等於 δ ( s , v ) ,也就是

δ ( s , v ) δ ( s , u ) + w ( u , v )
通過前面的假設,則必定有 δ ( s , v ) d [ u ] + w ( u , v ) = d [ v ] 。這說明,中間的過程的任意一個階段產生的結果d[v]都不會比 δ (s,v)還要小

最短路徑演算法的一般思路問題一:錯誤的選邊導致複雜度為指數級別

構造如下結構的圖

邊的權值按照 2 n / 2 方式分配,圖中給出的6個點的示例,如果全部顯示的邊( v 0 , v 2 )的權值為 2 n / 2 ,並依次遞減到1

這裡寫圖片描述
假設源點為 v 0 ,初始化選擇的路徑如下,可以得到從源點到各個點的路徑長度。

這裡寫圖片描述

此時,Relax( v 4 , v 6 )的邊,會更新 v 0 v 6 的路徑長度為13

這裡寫圖片描述
再Relax( v 2 ,