最短路

本文介紹4種算法:SPFA, Dijkstra, Bellman-Ford, Floyd
PS:文中分大小寫。 圖爲G(V,E),V爲節點集合,E爲邊集合,但v表示某個節點(v∈V)

Dijkstra:

  • 原理:通過每一次解壓節點min{key[v]|v∈G-已經生成的最短路徑的樹}並添加到樹中,並將所有以v爲起點的邊鬆弛(key域),來達到最短路(貪心)
  • 注意:圖中不能有負權,不能查是否有負權迴路
  • 步驟:
    1. 初始化key域。每個key[v]=INF,v∈V
    2. 將最短路起點S的key[S] = 0
    3. 定義一個優先隊列 priority_queue (#include <queue>) ,並將S節點(可以考慮用pair來綁定key域,也可以用一個結構來綁定)壓入。//STL的隊列默認爲最大優先,故要創建一個比較類,重載()來實現最小堆
    4. 循環(直到隊列爲空)每一次解壓最小值, 將最小key域所綁定的節點v解壓出來並添加到樹中(直接用一個bool數組來確定是否在樹中即可,要輸出路徑就定義一個父親域並維護)將v爲起點的邊全部鬆弛一遍,維護key域。並將這條邊的終點壓入隊列。
  • 分析:時間複雜度O(N^2)
  • 適用於:稠密圖
  • 優化:優化堆的實現,即手打FIB堆或其它比STL快的堆= =。可以達到O(NlogN)

Bellman-Ford:

  • 原理:通過V-1次(最短路長度最多有V-1條邊嘛- -)對每一條邊鬆弛,來實現最短路(同樣是貪心)
  • 好處:圖中可以有負權,也能判斷是否有負權迴路
  • 步驟:
    1. 初始化key域。每個key[v]=INF,v∈V
    2. 循環(1~n-1)
    3. 枚舉所有邊進行鬆弛
    4. 判斷是否有迴路,循環(1~V)
      如果以v∈V爲起點的邊還能鬆弛,即有迴路。(自己拿算導看證明哈,或者谷歌百度,或者自己想)
  • 分析:時間複雜度O(VE)
  • 適用於:稀疏圖和負權圖
  • 優化:我布吉島

Floyd:

4行代碼:

for(k = 1; k <= N; k++)
	for(i = 1; i <= N; i++)
		for(j = 1; j <= N; j++)
			node[i][j] = min(node[i][j], node[i][k]+node[k][j]);

SPFA:(全名爲:ShortestPathFasterAlgorithm)

百科

看到好文章,直接轉過來了(點擊打開鏈接

我們知道,求一個圖中的單源最短路徑有Dijkstra、Ford這兩種經典的算法。其複雜度均是O(N2),通過堆的優化,Dijkstra可以達到O(NlogN)的複雜度。但對於一些十分稀疏的圖,這個複雜度就有些浪費了。當一個圖中的邊數e遠遠小於N2時,我們就考慮是否有一種算法,其時間複雜度只跟邊數e有關係。於是SPFA誕生了。

我們知道,Dijkstra的O(N2)是因爲又一重循環是爲了找到目前的Dist值最小的節點,於是我們想,能不能不找最小的,只是按照一定的順序更新就可以了。那麼算法的雛形就出來了,設S爲源點:

Quene←S
While Quene not empty do
    Tmp←Quene
    For each node i with an edge to Tmp do
        If Dist[i] > Dist[Tmp]+length(edge(i,Tmp)) then
            Dist[i]←Dist[Tmp]+length(edge(i,Tmp))
            If i not in the Quene then
                Quene←i

這就是傳說中的SPFA。我們來看看它的執行過程:

爲了圖片的美觀,我隱藏了頂點的標號。左上角的頂點爲源點,黃的的點表示在隊列中,綠色的點表示正在處理:

至此,隊列空,算法結束。

爲什麼它能收斂呢?爲什麼它不會一直循環下去呢?因爲總有一刻Dist[i]已經達到最小值,這時i這個頂點就再也不會入隊了,並且當訪問到i的時候,與i鄰接的頂點也會被更新。所以總有一刻,所有的Dist都是最優值,算法結束。

可以證明,假設每個節點的平均入隊次數是k,那麼時間複雜度就是O(ke)。而這裏的k幾乎可以認爲是一個常數,所以簡算之後時間複雜度爲O(e)。

如果時間複雜度優於這個值,就是說我們並沒有處理完圖中所有的邊,就不可能一定可以得到最優解,所以,O(e)是所期望的最好的複雜度。
PS:  有可能會更新,,歡迎大家吐槽

發佈了40 篇原創文章 · 獲贊 2 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章