代码随想录 最短路径问题(dijkstra,Bellman_ford, Floyd,A*)

Dijkstra

朴素版

朴素版

解题思路

和prime方法的思路是一样的,只不过这次我们不找离最小生成树最近的节点,而是寻找离源点距离最近的节点,同时也要记录节点是否被访问过,以避免重复访问。因此,minDist变成用来存储 每一个节点距离源点的最小距离。

堆优化版

堆优化版

解题思路

用邻接表存储连接的节点和权重,使用小顶堆自动排序边,就不需要额外遍历一遍边进行排序

Bellman_ford

该算法用来处理权重包含负数的情况

基础版

基础版

解题思路

对一个节点来说,relax就是找到节点最小的入度值。这里我们还是使用minDist数组存储入度的最小值。对于每一个节点,遍历和其相连的节点,把边的权值和相连的节点的入度值之和和当前节点的入度最小值进行比较,以此更新每个节点的最小值。这其实是一个动态规划的思想。 对于松弛次数,我们需要对除了起点的所有节点进行松弛,每次松弛代表着与起点n条边的节点的最短距离,由于起点到终点,最多是n-1条边相连,所以是n - 1次.

SPFA

SPFA
该方法适用于无负值回路的情况.

解题思路

每一次松弛所有节点是比较浪费的,因为真正有效的松弛只有当松弛该节点相邻的节点。因此,我们只需要对上一次松弛的时候更新过的节点作为出发节点所连接的边进行松弛就够了。于是我们利用队列来记录上次更新的节点。每次将队列头部的元素作为当前的节点,把它弹出后再将其相邻的节点存入队列即可,直到队列为空结束该遍历。

注意,其时间复杂度根据图的稠密度而决定。

判断负权回路

判断负权回路

解题思路

当松弛n次的时候,如果结果有变化,那么就是有负权回路,反之没有。
对于SPFA来说,我们需要判断是否节点加入队列的次数超过了n-1次,超过了就说明有,没超过则说明没有

注意,其时间复杂度根据图的稠密度而决定。

单源有限最短路

单源有限最短路
该方法用于解决限制步数的最短路问题

解题思路

假设步数为k,那么一般思路就是松弛 k + 1 次就好。但本题有个陷阱,就是如果你每次都根据当前的minDist进行松弛,会得不到正确结果,因为他会同时更新所有节点的最小值,而我们的需求是至多经过k个节点的限制。解决方法是根据上一次的minDist进行松弛,这样每次就会只更新一个节点的结果。

对于SPFA,我们需要记录每一轮松弛压入队列的节点数量,然后下一次弹出之前记录过的数量的元素出来即可,同时利用数组标记存入过的节点,避免它们重复压入队列中

注意,其时间复杂度根据图的稠密度而决定。

Floyd算法

Floyd算法
该方法用于解决多源最短路问题

解题思路

利用动态规划的思想,将两个节点A,B的最短路径拆分为A to K, K to B 的最短路径,随后对A to K 和 K to B 进行同样的拆分,因此我们只需要确定之前的状态就能得到之后的状态。

A* 算法

A* 算法

解题思路

在广搜的基础上,通过启发式函数为每个节点计算一个权值,根据权值的大小进行节点的遍历,在本题中,启发式函数通过计算和下一个节点遍历的距离来得到权值,通过小顶堆来自动排序权值。

posted @ 2024-08-21 05:47  不进育碧不改名  阅读(3)  评论(0编辑  收藏  举报