原理解释
Dijkstra算法是通过贪心+BFS+动态规划实现的,可以用来计算单个点(源点)到其余任一点的距离大小。
Dijkstra算法的实现分为以下几步:
-
定义并初始化数组dis[N]
,其中 disi 表示源点当前距离 i 点的最短距离,再定义一个 bool 数组 vis[N]
, visi 代表第 i 个点是否被拓展过(即是否达到了最优解)。
-
从未被拓展的点中找出一个离源点最近的点 x(此时它已经是最优解),通过这个点依次松弛和它联通的每一个点距离源点的距离,同时将所松弛的点加入到队列当中。
-
等到队列中没有元素存在之后,结束函数,此时 dis[N]
中的每个点 disi 即代表着距离源点的最小距离。
代码实现
朴素法
1 2 3
| struct Edge { int x, w; }; vector<Edge> g[N]; int dist[N];
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| void dijkstra(int st) { memset(dist, 0x3f, sizeof dist); dist[st] = 0; bitset<N> vis;
for (int i = 1; i <= n; i++) { int t = -1; for (int j = 1; j <= n; j++) if (t == -1 || (!vis[j] && dist[j] < dist[t])) t = j;
vis[t] = true; for (auto &y : g[t]) if (!vis[y.x] && d[y.x] > d[t] + y.w) d[y.x] = d[t] + y.w; } }
|
队列 / 堆优化
vector 存图
1 2 3 4 5 6 7
| struct Edge { int x, w; bool operator < (const Edge &u) const { return w > u.w; } }; vector<Edge> g[N]; int dist[N];
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| void dijkstra(int st) { memset(dist, 0x3f, sizeof dist); dist[st] = 0; bitset<N> vis; priority_queue<Edge> heap; heap.push({st, dist[st]});
while (heap.size()) { int t = heap.top().x; heap.pop();
if (vis[t]) continue; vis[t] = true;
for (auto &y : g[t]) { if (!vis[y.x] && dist[y.x] > dist[t] + y.w) { dist[y.x] = dist[t] + y.w; heap.push({y.x, dist[y.x]}); } } } }
|
链式前向星
1 2 3 4 5 6 7 8 9 10
| struct Edge { int ver, val; bool operator < (const Edge &rhs) const { return val > rhs.val; } };
int n, m, st; int h[N], e[M], ne[M], w[M], idx; int dist[N]; bool vis[N];
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| void dijkstra(int st) { priority_queue<Edge> heap; memset(dist, 0x3f, sizeof dist), memset(vis, 0, sizeof vis); dist[st] = 0; heap.push({st, 0}); while (!heap.empty()) { auto [ver, val] = heap.top(); heap.pop(); if (vis[ver]) continue; vis[ver] = true; for (int i = h[ver]; ~i; i = ne[i]) { int to = e[i]; if (dist[to] > dist[ver] + w[i]) { dist[to] = dist[ver] + w[i]; heap.push({j, dist[j]}); } } } }
|