最短路徑問題


    由於要考試了,這里只是簡單的羅列一下,考試完畢之后繼續完善~

單元最短路徑

單元最短路徑有很多變體問題,比如單元目的最短路徑,最短路徑也有很多性質~,這些性質是算法正確性的基礎,這些考試之后來完善,

關於每個算法都要用到的松弛操作如下

RELAX(u,v,w)
    if d[v] > d[u]+w(u,v)
        d[v]= d[u]+w(u,v)
        father[v]=u

關於每個算法的初始化操作也寫在前面

INITIALIZE-SINGLE-SOURCE(G,s)
    for each vertex v in G
         d[v]= MAX
         father[v]=NIL
    d[s]=0

首先重點是Bellman-Ford算法,該算法能夠識別負權重環

BELLMAN-FORD(G,w,s)
    INITIALIZE-SINGLE-SOURCE(G,s)
    for i = 1 to |V|-1
        do for each edge (u,v) in E(G)
             RELAX(u,v,w)
    for each edge (u,v) in E(G)        //沒有收斂,存在負權環
       if d[v]>d[u]+w(u,v)
           return FALSE
    return TRUE

時間復雜度為O(VE)

接下來是DAG有向無環圖的單元最短路徑

//這里考慮是針對順序進行松弛,但是根據路徑松弛性質,必須按照路徑的順序進行,所以這里結合拓撲排序進行計算
DAG-SHORTEST-PATH(G,w,s)
    topologically sort the vertices of G
    INITIALIZE-SINGLE-SOURCE(G,s)
    for each vertex u, taken in toplogically sorted order
        for each vertex v in Adj[u]
            RELAX(u,v,w)

時間復雜度為O(V+E)

接下來是Dijkstra算法

DIJKSTRA(G,w,s)
    INITIALIZE-SINGLE-SOURCE(G,s)
    S=空集
    Q=V[G]
    while Q!=空集
         do u=EXTRACT-MIN(Q)
             S=S+{u}
             for each vertex v in Adj[u]
                 RELAX(u,v,w)

這個時間復雜度的分析和Prim算法的時間復雜度分析相同

V次EXTRACT-MIN操作,內隱含E次的DECREASE-KEY操作

則分析如下表:

這個算法在后面算任意兩點之間計算最短距離的時候,可以通過變化權重轉換為此算法,針對稀疏圖增加能夠提升效率

差分約束和最短路徑

這里描述的是一個解決的實際問題,差分約束問題轉換為單元最短路徑問題的解決

差分約束的一個問題描述:線性規划的一種,目標是找出可滿足解,而不是線性規划中的最優解。而且條件式的形式比較固定,每一項中有兩個變量的差組成,變換為矩陣每行只有一個1和一個-1 。實例如下:

線面是此問題轉換為最短路徑的方法,針對矩陣進行轉置,得到一個n*m的矩陣,轉置后的矩陣為這樣一種矩陣n為頂點,m為邊,位置i,j的數值信息表示邊的信息,信息如下,0第i個頂點和第j條邊無關系,1表示第j條邊進入i,-1表示第j條邊離開i,權中為對應的后面的j位置的信息

一個簡單的方法可以直接根據公式換圖更方便,某個減去某個表示第i個頂點到減去頂點有一個大小的權重...

上例轉換如下圖:

接下來添加一個虛擬的點,其到各個頂點的權重為0,這時候求的該點單元最短路徑的及為差分的一個滿足解

證明后續補充...

每對頂點間的最短路徑問題

根據前置矩陣輸出最短路徑的偽代碼這里就不給出了,比較簡單。

首先說明最短路徑具有最優子結構,所以這里考慮動態規划算法~

首先是一個跟矩陣相乘很相似的算法,其考慮是根據邊考慮子結構,比如把路徑p的最短路徑分解為i到k的最短路徑+k到j的權重,這里是每個子問題減去1,

偽代碼比較容易實現:

算法導論一書中進行優化的時候是轉換為矩陣的乘方問題,所以可以遞歸,但是這里可以直接從動態規划子結構的划分方面考慮,比如最短路徑p分解為i到k的最短路徑和k到j的最短路徑,這也是一個子結構,這里可以從1擴展到2,然后路徑長度為2的擴展到4,4的擴展到8...所以書中的偽代碼相似;

這樣就行了,因為上面慢的時間復雜度為V的四次方,這里提升到V的三次方*lgV,效率還是比較低。

接下來介紹另外一個更加優秀的動態規划方法,其子結構考慮非常好。

Floyd-Warshall

這個算法的最短路徑的子結構考慮的是其路徑包含的中間節點的個數

偽代碼如下:

FOLYD-WARSHALL(W)
    n = rows[w]
    D0 = w 
    for k =1 to n 
        for i = 1 to n 
            for j=1 to n
                dij(k) = min(dij(k-1),dik(k-1),dkj(k-1))

計算過程中保持計算前置矩陣。

算法導論一書中該處印刷有些錯誤,第二版...

時間復雜度為V的三次方

有向圖的傳遞閉包

上面的算法稍微修改即可,針對上述算法中的min和+法直接利用邏輯或和邏輯與代替即可。

稀疏圖上的Johnson算法

原理將圖轉換為無負權重的圖,利用上面的Dijkstra算法。

每個頂點加一個權重函數,最短路徑不變,增加權重方法和差分約束轉換方法很相似:

每個頂點增加的權重就是增加新的節點到該節點的最短路徑...

偽代碼:

重點的輪廓給出了,我會慢慢補充一些知識進來的~

 

轉載請注明出處,謝謝~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM