Dijkstra最短路算法(单源最短路)
过程详解:[最短路径问题]—Dijkstra 算法最详解 - zdr0的文章 - 知乎 https://zhuanlan.zhihu.com/p/129373740
下面是我的代码模板,因为是稠密图所以选择邻接矩阵
int n, m;
int g[N][N]; // 邻接矩阵
int dist[N]; // 当前点距离起点的最短距离
bool st[N]; // 当前点的最短距离是否确定
int dijkstra() {
memset(dist, 0x3f, sizeof dist); // 所有距离初始化成无穷大
dist[1] = 0; // 第一个点确定
for (int i = 0; i < n; ++i) { // 循环n次 每个点都遍历一次
int t = -1;
for (int j = 1; j <= n; ++j) {
// t表示当前点是否确定点
// 如果t确定了还不是最小的点
if (!st[j] && (t == -1 || dist[t] > dist[j])) {
t = j;
}
}
st[t] = true; // t确定将这个点标记
for (int j = 1; j <= n; ++j) {
dist[j] = min(dist[j], dist[t] + g[t][j]); // 将这个点之前的路线加起来
}
}
if(dist[n] == 0x3f3f3f3f)
return -1;
else
return dist[n];
}
堆优化版:
这里是使用vector模拟的邻接表
#define MAXN 0x3f3f3f3f
typedef pair<int, int> PII;
const int N = 1e5 + 5;
// v表示从a点到b点中的b点 cost是从a到b的边的权重
struct Edge {
int v, cost;
};
int n, m;
vector<Edge> g[N];
int dist[N]; // 所有点到起点的距离
bool st[N]; // 确定当前点是否是最小的点
// x到y的距离为z
void add(int x, int y, int z) {
Edge tmp = {y, z};
g[x].push_back(tmp);
}
int dijikstra(int start) {
for(int i = 1; i <= n; ++i) dist[i] = MAXN;
dist[start] = 0;
priority_queue<PII, vector<PII>, greater<PII>> q;
q.push({0, start}); // first存储距离 second存储节点编号
while(!q.empty()) {
auto t = q.top();
q.pop();
int num = t.second, distance = t.first;
if(st[num]) continue;
st[num] = true;
for(int i = 0; i < g[num].size(); ++i) {
int v = g[num][i].v; // 当前所在的节点
int cost = g[num][i].cost; // 从num到i的距离
if(dist[v] > distance + cost) {
dist[v] = distance + cost;
q.push({dist[v], v});
}
}
}
if(dist[n] == MAXN)
return -1;
else
return dist[n];
}