總結分析
- 總共分成兩步
- 第一步:尋找一個這次要確認的結點
- 第二步:利用這次確認的結點,對所有未確認結點到源點的距離進行松弛
- 松弛:比如原本記錄源點到結點4的距離為6,這次確認了結點2,源點到結點2距離為2,結點2到結點4的距離為3,總距離為5,即可更新結點4到源點的距離
- 二維數組G,記錄結點間的距離;數組confirmed,記錄結點是否被確認,初始化為false;數組dis,記錄結點到源點的距離,初始化為inf(無限大)
- 進入dijkstra算法前先確定源點source,我們就可以確認源點到源點的距離dis[source]=0
- 第一個for循環,只需要確認n-1個結點即可,因為確定第n-1個結點后,會更新第n個結點到源點的距離
- 第二個for循環,尋找這次要確認的結點,要滿足兩個條件
- 該結點未被確認
- 該結點到源點的距離是目前已知所有距離中最小的
- 第三個for循環,利用這次確認的結點,對所有未確認的結點到源點的距離進行松弛
注意
- 時間復雜度O(n²)
- 單源最短路徑
- 解決不了負權圖,有可能出錯
題目
從0點出發,尋找到達每一個結點的最短路徑(單源最短路徑問題)
代碼
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define n 7
#define inf 233
vector<vector<int>> G(n, vector<int>(n,inf));
vector<int> dijkstra(vector<vector<int>>, int source) {
vector<bool> confirmed(n, false);
vector<int> dis(n, inf);
dis[source] = 0;
for (int i = 0; i < n - 1; i++) {
int curr=-1;
for (int j = 0; j < n; j++) {
if (!confirmed[j] && (curr == -1 || dis[curr] > dis[j])) curr = j;
}
confirmed[curr] = true;
for (int j = 0; j < n; j++) {
if(!confirmed[j]&&dis[j]>G[curr][j]+dis[curr]) dis[j] = G[curr][j]+dis[curr];
}
}
return dis;
}
int main() {
G[0][2] = 2;
G[0][1] = 5;
G[1][3] = 1;
G[1][4] = 6;
G[1][0] = 5;
G[2][3] = 6;
G[2][5] = 8;
G[2][0] = 2;
G[3][2] = 6;
G[3][1] = 1;
G[3][4] = 1;
G[3][5] = 2;
G[4][1] = 6;
G[4][3] = 1;
G[4][6] = 7;
G[5][2] = 8;
G[5][3] = 2;
G[5][6] = 3;
G[6][4] = 7;
G[6][5] = 3;
vector<int> ans = dijkstra(G, 0);
for (auto a : ans) cout << a << " ";
cout << endl;
return 0;
}