最短路径
一、Dijkstra(单源最短路)
1.Dijkstra算法简介
迪杰斯特拉算法(Dijkstra’s Algorithm)是一种经典的最短路径算法,用于寻找加权图中从源点到其他各个顶点的最短路径。该算法常用于单源最短路径问题,即已知图中一个起点(源点),计算它到其他所有顶点的最短路径,前提是权重是非负的。
2. 算法思想
迪杰斯特拉算法通过逐步扩展最短路径来构建最终的最短路径树,其基本思想如下:
- 从起点出发,逐步找到离起点最近的顶点,并计算路径长度。
- 每次选出当前未访问过的最短路径的顶点,更新起点到其他顶点的最短距离。
- 直到所有顶点都被访问,算法结束。
3. 算法步骤
- 初始化:设定源点到自身的距离为0,其他顶点到源点的距离为∞(表示不可达)。
- 选取未访问的顶点中距离源点最近的顶点作为当前顶点,记为
u
,标记其为已访问。 - 遍历从顶点
u
出发的所有边,更新从源点到邻接点的距离。如果从源点通过u
到达邻接点的距离更短,则更新邻接点的距离。 - 重复步骤2和步骤3,直到所有顶点都被访问。
- 最终结果是源点到每个顶点的最短路径。
4. 代码实现(主要部分)
1 |
|
二、Floyd(多源最短路)
1.Floyd算法简介
Floyd算法(弗洛伊德算法)是一种用于求解加权图中任意两点最短路径的经典算法。与Dijkstra算法和Bellman-Ford算法不同的是,Floyd算法不只是计算单点到其他点的最短路径,而是能够计算出所有点之间的最短路径,因此常用于多源最短路径问题。
2.算法思想
Floyd算法的核心思想是使用动态规划的方式,不断尝试在两点之间插入中间节点,并更新最短路径。具体而言,假设图中有 (n) 个顶点,Floyd算法使用三重循环逐步检查是否能通过某个中间顶点 (k) 使两个顶点 (i) 和 (j) 的距离更短。
3.算法步骤
设dist[i][j]
表示节点 (i) 到节点 (j) 的最短距离。
算法流程如下:
- 初始化距离矩阵
dist
。若顶点 (i) 到 (j) 有直接边权,则dist[i][j]
设为该边权;否则设为一个较大的值(如INF
)。 - 依次遍历每个节点 (k),对于每对节点 (i) 和 (j),尝试通过节点 (k) 更新
dist[i][j] = min(dist[i][k] + dist[k][j])
- 经过上述操作,
dist[i][j]
会记录 (i) 到 (j) 的最短路径。
4.代码实现(主要部分)
1 |
|
三、SPFA(含有负边权单源最短路)
1.SPFA算法简介
SPFA(Shortest Path Faster Algorithm)是Bellman-Ford算法的队列优化版本,用于求解单源最短路径问题。该算法适用于含负权边(前提是不含负权回路)的图,并能检测图中是否存在负权环。其平均时间复杂度为 O(E)O(E),最坏情况下为 O(VE)O(V**E),在稀疏图中表现优异。
2.算法思想
-
利用队列维护待更新的顶点集合,只对队列中的节点进行松弛操作,从而减少不必要的重复更新。
-
每当从队列中取出一个顶点 u 后,遍历其所有出边,如果能通过 u 更新原点到 u的邻接点 v 的距离,则将 v 放入队列(如果它还不在队列中)。
3.算法步骤
- 初始化:设置源点到自身的距离为0,其他顶点为无穷大(
INF
)。将源点加入队列,并标记为“在队列中”。 - 取出队首顶点:取出队列头部顶点
u
,标记为“不在队列中”。 - 遍历邻接边:对
u
的所有邻接边u→v
进行松弛操作:若dist[v] > dist[u] + weight(u, v)
,则更新dist[v]
。 - 入队条件:若
v
的距离被更新且当前不在队列中,则将v
加入队列尾部,并标记为“在队列中”。 - 循环终止条件:重复上述过程直到队列为空。
- 负权环检测:若某个顶点入队次数超过顶点总数
n
,说明图中存在负权环。
4.代码实现(主要部分)
1 |
|
最短路径
http://jayzencode.top/posts/15bc60d8/