问题背景
最短路径问题是图论中的经典场景。在带权有向图中,我们需要找到从某个起点到目标顶点的路径,使得路径上所有边的权值总和最小。根据应用场景的不同(如单源、全源、是否存在负权边),我们有几种不同的策略。
Dijkstra 算法:贪心策略的单源解法
Dijkstra 算法是解决非负权图单源最短路径的经典方案。它的核心思想是贪心:每次从未确定最短路径的节点中,选出当前距离起点最近的一个,标记为'已确定',并用它去松弛(更新)所有邻接点的距离估计值。
需要注意的是,该算法不能处理包含负权边的图。一旦存在负权边,贪心选择的最短路径可能会被后续更小的负权边推翻,导致结果错误。

// src 是选定的起点,dist 记录起点到各点的最短路径,pPath 记录到每个点的最短路径的前驱顶点下标
void Dijkstra(const V& src, std::vector<W>& dist, std::vector<int>& pPath) {
size_t srci = GetVertexIndex(src);
size_t n = _vertexs.size();
// 初始化距离为无穷大,前驱为 -1
dist.resize(n, MAX_W);
pPath.resize(n, -1);
dist[srci] = 0;
pPath[srci] = srci; // 起点到自己的前驱是自己
// S 集合:已经确定最短路径的顶点集合
std::vector<bool> S(n, false);
for (size_t j = 0; j < n; ++j) {
// 1. 在未确定的节点中,选出距离最小的节点 u
int u = 0;
W min_dist = MAX_W;
for (size_t i = 0; i < n; ++i) {
if (!S[i] && dist[i] < min_dist) {
u = <>(i);
min_dist = dist[i];
}
}
S[u] = ;
( v = ; v < n; ++v) {
(!S[v] && _matrix[u][v] != MAX_W && dist[u] + _matrix[u][v] < dist[v]) {
dist[v] = dist[u] + _matrix[u][v];
pPath[v] = u;
}
}
}
}



