1. 项目背景与问题定义
单源最短路径(Single-Source Shortest Path,SSSP)是图论中的经典问题,也是算法竞赛中的高频考点。洛谷P4779作为标准模板题,要求实现一个能够处理带权有向图的Dijkstra算法,解决从固定起点到图中所有其他节点的最短路径问题。这个问题在实际应用中广泛存在,比如导航软件中的路线规划、网络路由中的最优路径选择等场景。
我第一次接触这个问题是在准备区域赛时,当时被各种优化版本绕得头晕。后来发现吃透标准版才是关键,就像练武术要先扎马步一样。本文将拆解最朴素的Dijkstra实现方案,适合算法入门者建立正确的思维模型。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 算法核心原理剖析
2.1 Dijkstra算法基本思想
Dijkstra算法的本质是贪心策略与动态规划的结合。其核心在于维护一个"已确定最短路径"的节点集合S,每次从剩余节点中选择当前距离起点最近的节点加入S,并松弛其邻接边。这个过程就像用探照灯一层层照亮地图,每次总是先照亮最近的未探索区域。
算法正确性的关键在于:在非负权图中,局部最优解能保证全局最优。用数学归纳法可以证明,当节点u被加入S时,dist[u]已经是最短距离。这个特性使得Dijkstra不能处理负权边——负权会破坏贪心选择的最优子结构。
2.2 时间复杂度分析
基础实现使用线性扫描查找最小距离节点:
- 每次查找最小值:O(V)
- 总共V次操作:O(V²)
- 松弛操作总次数:O(E)
- 合计复杂度:O(V² + E)
对于稀疏图(E≈V),这显然不够高效。后面我们会看到如何用优先队列优化到O((V+E)logV)。
3. 标准版实现详解
3.1 数据结构设计
cpp复制const int MAXN = 1e5 + 5;
const int INF = 0x3f3f3f3f;
struct Edge {
int to, weight;
};
vector<Edge> adj[MAXN]; // 邻接表存图
int dist[MAXN]; // 存储最短距离
bool visited[MAXN]; // 标记是否已确定最短路径
这里有几个关键点:
- 邻接表比邻接矩阵更节省空间,尤其适合稀疏图
- INF
