Dijkstra和Floyd演算法遍歷圖的核心
-
Dijkstra(迪傑斯特拉)演算法
-
解決的問題
使用者指定一個頂點\(V_k\),求出\(V_i|_1^N\)與\(V_k\)的最短路徑及其長度。
-
演算法的核心
說到底它是一種“貪心演算法”,通過在每一步做出區域性最優決策來解決問題,希望找到全域性最小值。
通俗地說就是:我們
\[\min\norm{\overrightarrow{V_kV_i}}=\min\norm{\overrightarrow{V_kV_{\min1}}}+\cdots+\min\norm{\overrightarrow{V_{\min M-1}V_i}}=\sum_{j=\min1}^{\min M}\min\norm{\overrightarrow{V_{j-1}V_{j}}} \]只有
按照“從\(V_k\)出發找相鄰的頂點,然後挑個最短的\(V_{\min1}\),並找離其最短的\(V_{\min2}\)”這樣的方法尋找時,才可能
得到最短路徑。這是我們尋找最短路徑的必要條件
:這就是將所有的區域性最短相加,
期望
如果增加了一箇中轉點之後路徑變小了則將中轉點填入最短路徑計算中,否則維持原路徑。這個中轉點的確定依據是:當前離\(V_k\)
【註釋[1]】如果存在另一箇中轉點使得\(\norm{\overrightarrow{V_kV_{\min j}}}\)不是最小,則說明該中轉點\(V_{TP}\)與\(V_k\)的距離小於\(V_{\min j}\)與\(V_k\)的距離,即\(\norm{\overrightarrow{V_kV_{\min j}}} \gt \norm{\overrightarrow{V_kV_{TP}}}\)
【註釋[2]】在註釋1中我們假設了所有的權值都是正數,當權值出現負數時這個矛盾將不成立,成為Dijkstra演算法的侷限性之一。
-
演算法的描述
-
如何手算做題
- 時間複雜度為\(O(N^2)=O(\norm{V}^2)\)(鄰接矩陣),\(O(\log_{2}\norm{{V}}\times\norm{E})\)(堆優化鄰接表)。
-
-
Floyd(弗洛伊德)演算法
-
解決的問題
可以解決Dijkstra演算法不能帶負權值的問題,並一口氣求了所有的點之間的最短距離。
-
演算法的核心
與Dijkstra演算法的思想是差不多的,只是Floyd不貪了[1],不再假設所有的權值為正數,所以在確定中轉點的時候
\[\small{\norm{\overrightarrow{V_kV_i}}^{(TP)}= \norm{\overrightarrow{V_kV_i}}^{pre(TP)} \le \norm{\overrightarrow{V_kV_{TP}}}^{pre(TP)}+\norm{\overrightarrow{V_{TP}V_i}}^{pre(TP)} \ ?\ \norm{\overrightarrow{V_kV_i}} \ :\ \norm{\overrightarrow{V_kV_{TP}}}+\norm{\overrightarrow{V_{TP}V_i}}} \]不會
去找距離\(V_k\)最近的點了,而是很野蠻地指定某一個或幾個點作為中轉點\(V_{TP}\),將其代入Dijkstra演算法的轉化條件
:(將每一個i都從1到N遍歷一遍,中轉點TP也是從1一直累積到N)如果中轉點可以使得兩目標點之間的距離縮小,那就將中轉點加入路徑集合,否則捨棄中轉點並保持不變。這樣也能保證區域性最優(區域性最短路徑)。剩下的看看書應該就能明白了。
【註釋[1]】Dijkstra演算法與Floyd演算法的不同就在兩者選取中轉點的方式不同,剩下的動態規劃思想都是一致的。
-
演算法的實現
-