迪杰斯特拉dijkstra算法总结
总结分析
- 总共分成两步
- 第一步:寻找一个这次要确认的结点
- 第二步:利用这次确认的结点,对所有未确认结点到源点的距离进行松弛
- 松弛:比如原本记录源点到结点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;
}