Dijkstra算法
758 字
4 分钟
Dijkstra算法

Dijkstra 算法
Dijkstra 算法用来求“非负权图”中的单源最短路。
单源最短路的意思是:从一个起点出发,到其他点的最短距离。
这里整理的是堆优化版本,适合边数比较多、点数也比较大的情况。
1、适用条件
Dijkstra 有一个前提:
边权不能是负数如果图中有负权边,就不能直接用 Dijkstra。
常见场景:
给 n 个点、m 条有向边,求 1 号点到 n 号点的最短距离。2、核心思想
维护一个距离数组:
dist[i]表示从起点到 i 的当前最短距离。
每次从还没有确定最短路的点中,取出距离最小的点 ver。因为所有边权非负,所以这个点的最短距离已经确定。
然后用它去更新邻点:
如果 dist[j] > dist[ver] + w就更新 dist[j]这个过程叫“松弛”。
3、为什么用小根堆
普通 Dijkstra 每次要扫描所有点找最小距离,复杂度高。
堆优化版本用优先队列维护:
{距离, 点编号}每次直接取出当前距离最小的点。
4、链式前向星存图
int h[N], e[M], w[M], ne[M], idx;含义:
h[a]:点 a 的第一条边e[i]:第 i 条边的终点w[i]:第 i 条边的权重ne[i]:同起点的下一条边加边:
void add(int a, int b, int c) { e[idx] = b; w[idx] = c; ne[idx] = h[a]; h[a] = idx++;}5、C++ 模板
#include <bits/stdc++.h>using namespace std;
typedef pair<int, int> PII;
const int N = 150010;const int M = 150010;const int INF = 0x3f3f3f3f;
int n, m;int h[N], e[M], w[M], ne[M], idx;int dista[N];bool st[N];
void add(int a, int b, int c) { e[idx] = b; w[idx] = c; ne[idx] = h[a]; h[a] = idx++;}
int dijkstra() { memset(dista, 0x3f, sizeof dista);
priority_queue<PII, vector<PII>, greater<PII>> heap;
dista[1] = 0; heap.push({0, 1});
while (!heap.empty()) { auto t = heap.top(); heap.pop();
int distance = t.first; int ver = t.second;
if (st[ver]) continue; st[ver] = true;
for (int i = h[ver]; i != -1; i = ne[i]) { int j = e[i];
if (dista[j] > distance + w[i]) { dista[j] = distance + w[i]; heap.push({dista[j], j}); } } }
if (dista[n] == INF) return -1; return dista[n];}
int main() { scanf("%d%d", &n, &m); memset(h, -1, sizeof h);
while (m--) { int a, b, c; scanf("%d%d%d", &a, &b, &c); add(a, b, c); }
printf("%d\n", dijkstra()); return 0;}6、st 数组的作用
bool st[N];st[ver] = true 表示 ver 的最短距离已经确定。
堆里可能会存在同一个点的多个距离版本。比如先入堆一个较大的距离,后来又找到更短距离。旧版本不会马上消失,所以取出来时要判断:
if (st[ver]) continue;7、容易写错的地方
(1)不要在 #define 后面加分号
如果写:
#define x first;会导致展开后多出分号。更推荐直接用:
t.firstt.second(2)初始化邻接表
memset(h, -1, sizeof h);没有初始化,遍历边时会出错。
(3)Dijkstra 不能处理负权边
只要出现负权边,就要考虑 Bellman-Ford、SPFA 或其他算法。
总结
Dijkstra 可以记成:
小根堆取最近点 -> 标记最短路已确定 -> 用它松弛所有出边它适合非负权图,是图论最短路里非常常用的模板。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!














