直接用 std::priority_queue 会出错,因其不支持修改已入队节点优先级;Dijkstra 需“更新”距离时只能重复入堆并跳过旧值,需初始化 dist 为 LLONG_MAX、用 long long 防溢出、检查不可达时输出 -1 而非原始值。

为什么直接用 std::priority_queue 会出错?
因为 std::priority_queue 不支持修改已入队节点的优先级。Dijkstra 算法中,当发现更短路径时需“更新”某节点的距离,但标准堆无法定位并调整已有元素——只能重复插入新记录,靠后续弹出时跳过旧值来模拟更新。
实操建议:
- 每次松弛成功(即找到更小距离)时,把
{new_dist, node_id}推入堆,不删旧项 - 出堆时检查
dist[node_id]是否等于当前弹出的new_dist,不等就continue - 初始化
dist数组为LLONG_MAX或足够大的数,dist[start] = 0
邻接表怎么建才不容易越界或漏边?
用 vector 存无向图/有向图最稳妥:外层索引是起点编号,内层每个 pair 是 {to_node, weight}。注意节点编号是否从 0 开始——读题不仔细常导致访问 graph[n] 越界。
常见错误现象:
立即学习“C++免费学习笔记(深入)”;
- 输入边时写成
graph[u].push_back({v, w})却忘了无向图要补graph[v].push_back({u, w}) - 节点数为
n,但graph只 reserve 了n-1个 vector - 权重类型用
int,但题目有 1e9 边权 × 路径长 1e5 → 溢出,必须用long long
如何处理不可达节点?
Dijkstra 本身不会给不可达节点赋“无穷大”以外的值,但你得主动判断。算法结束后,若 dist[target] == LLONG_MAX,说明不可达——不能直接输出该值,要按题目要求输出 -1 或特定字符串。
使用场景:
- 单源多终点查询:跑一遍 Dijkstra 后批量查
dist[i] - 只查某终点:中途加个
if (u == target) break;可提前退出(但注意不能省略松弛操作) - 需要路径还原:额外开
prev数组记录前驱节点,回溯时用栈避免递归
std::priority_queue 的比较函数为什么常写成 greater?
因为默认是大根堆,而 Dijkstra 需要每次取最小距离节点。priority_queue 才是小根堆。如果手写 lambda,注意参数顺序和返回值:返回 true 表示前面的“优先级更低”,会被沉底。
性能影响:
- 用
greater比自定义 lambda 略快(编译期确定) - 不要在循环里反复构造堆,声明一次复用
- 如果图稀疏(边数 ≈ 节点数),堆操作主导复杂度;若稠密,邻接矩阵反而更稳(但空间 O(n²))









