獲取多條最短路徑的Dijkstra演算法

2021-07-30 00:21:01 字數 1649 閱讀 3579

dijkstra演算法是單源最短路徑經典演算法,一般用於所有邊的權為非負數的情況下,有向圖和無向圖均可。

效率方面:儲存圖模型的資料結構有很多種,使用鄰接矩陣的話其空間複雜度都為o(e^2)。而如果是稀疏圖,使用鄰接鍊錶更划算,空間複雜度為o(v+e)。在每次搜尋離起點最近的點方面,這裡用的還是vector(最近在複習vector….),所以每一次的時間複雜度還是o(n),其實可以使用優先佇列實現,將時間複雜度降到o(logn)。

路徑數目方面:一般演算法使用乙個一維陣列記錄每個點的前驅點,以此記錄指定點到每個點的最短路徑。但是由於每個點只保留乙個前驅點,因此最後得到的最短路徑只有一條,尋找過程中其他距離相等的最短路徑會被拋棄,而做到儲存多條最短路徑,可以讓每乙個點都維護乙個自己的前驅點陣列。對於點i,在遇到距離相同的路徑的時候,把i在這條路徑的前驅點記錄下來,而不是拋棄或者覆蓋;而遇到更短的路徑的時候,把i的前驅點陣列清空,存入新的前驅點。這樣最後每個點的前驅陣列大小都不同。

/**

** @param start 起點

* @param dest 終點

* @param adj 鄰接鍊錶。adj[i][k]表示節點i的第k個鄰接點的索引

* @param distance 到起點的距離。distance[i]表示起點到點i的距離

* @return prevpoints 前驅點陣列。 prevpoints[k]表示到達點k的最短路徑中的所有前驅點

*/vector

> dijkstra(vector

> adj,int start, int dest=-2, vector

distance)

else

}if (prevpoints[dest][0] == start)

for (int i = 1; i < num; ++i)

}//如果是要找指定終點dest,可以提前剪枝,

//但這樣的話未訪問的點的路徑就不能保證是最短的。

if (tovisit != -1 && !(dest != -2 && tovisit == dest) ) else

if (distance[adj[tovisit][k]] == distance[tovisit] + 1) }}

} else

}return prevpoints;

}

得到的前驅點陣列可以用dfs從終點往回獲取。

if (prevpoints[dest][0] != -1)

/***

* @param start 起點

* @param index 終點

* @param prevpoints 前驅點陣列。prevpoints[k]表示到達點k的最短路徑中的所有前驅點

* @return paths 路徑。paths[k]表示從start到index的第k條最短路徑

*/vector

> getpaths(int start,int index, vector

>& prevpoints)

if(midpaths.empty()) else}}

else

return midpaths;

}

多條最短路徑的求解

最近在練習pat,遇到乙個要求解最短路徑的題,很自然地想起了這學期剛學的迪傑斯特拉演算法。但是這個問題要求解多條最短路徑,而迪傑斯特拉演算法只能求出其中一條最短路徑及其距離,所以要在運用迪傑斯特拉演算法演算法的基礎上,想想怎樣求解多條最短路徑。後來受到某個的啟發,想到了乙個解決辦法,演算法思想大概如...

Dijkstra演算法多條最短路徑下最短路徑的記錄

1.我們在使用dijkstra演算法求解源點到其餘頂點的最短路徑的時候,在大多數情況下最短路徑是只有一條的,但是也有可能存在著多條最短路徑的情況,所以之前使用整型的pre陣列來記錄當前節點的前驅節點的方法就不再適用這個問題了,所以需要另外的資料結構來進行記錄,而題目中告訴我們可能存在著多條最短的路徑...

兩點間多條最短路徑

最短路徑的求法可能都知道,弗洛伊德和迪克斯特拉。這兩種方法都是求一條最短路徑,如果你想求多條最短路徑那就只能選擇其他方法了。網上已經有幾種演算法可以求多條最短路徑,最常見的就是刪邊法 迪克斯特拉。就是用狄克斯特拉求出一條最短路徑然後把最短路徑上的邊一條一條的刪除然後再求最短路徑。這個方法比較容易想但...