单/多源最短路的三种算法 — dijkstra & spfa & floyd
什么是最短路
单源最短路:计算图中一个点到其他各点的最短距离
多源最短路:计算图中多个点到其他各点的最短距离
单源最短路 — dijkstra 算法
算法描述
main 函数:用vector数组存边,初始化一维数组 dist 来表示起点到其他各点的距离(到自己为 0,其他点为 INF),将初始边(目标点为起点,权值为 0)加入到优先队列 queue 中
dijkstra 函数:抛出优先队列的 top 边,若这个边的权值比现在到这个目标点的权值大(说明起点到该点的长度又更新了,而且那个边肯定在这个边前面),就跳过,否则就疏松以这个点为起点的所有边,若通过这个点,起始点到其他的点的距离有减小的,则把路径减小的目标点和减小后的距离加入到优先队列中,重复操作
算法应用
说明:这个题有点意思(
题目描述
知识点:最短路,最短路的优化
贝克兰德有n个城镇,这些城镇之间有m条道路连接,每条道路有一个长度l。
zf在其中k个城镇设置了治安点。当一个城镇发生事件时,任意一个治安点都可以派人前往。但是为了节省资源,往往会选择距离最近的治安点。
那么请问,对于每一个城镇,最近的治安点距离为多少。
思路
这个题要求算部分点到其他点的最短距离,因此看起来是一个多源最短路,但是你如果执行多次 dijkstra 你就超时了,所以我们要多设立一个虚拟点 s,把所有的治安点往这个虚拟点上拉一条距离为 0的边(无向),以这个点为起点计算到其他点的最短路即满足要求
代码
1 | /* |
单源最短路 — spfa 算法 可以判断负环!
算法描述
将某个点的序号 x 作为 spfa 函数的输入,则从这个点开始进行单源最短路,如果点 v 通过当前点 u 到输入点 x 的距离变小,那么更新距离值,并且如果 v 不在队列中,就将 v 加入到队列里,对于每个点记录它们加入队列的次数,如果大于总点数 n ,就判定为当前图中存在负环。
题目描述
知识点:最短路
克莱恩在一场冒险中得到了得到了一个破损的魔法阵,这个魔法阵是一个有n个点m条边的有向有环图,任意两点之间最多只有一条边,每条边有一个能量值a(可能是负数,别问问就是magical),不存在负环。
克莱恩试图去修补这个魔法阵。已知,这个魔法阵缺少了3条边,且已经知道这3条边的起点和终点(有向)。对于每条边,克莱恩要赋予其一个能量值c,为了避免邪神出现,修补过程以及结束后也不能出现负环。
请问每次的最小花费是多少(保证有解,可以是负数)。
题目思路
修补过程及结束后不能出现负环,则枚举边权来找到最大的可以使图中出现负环的权值,那么给这个权值加一图中就没有负环(其实可以二分权值直接找到答案)
代码示例
1 | /* |
多源最短路 — floyd 算法
算法描述
floyd 算法很简单,先在邻接矩阵中将直接相连的边的权值更新,然后对于任意两个点,以任意一个点为中介,更新两个点之间的权值,注意将当成中介的点放在最外面的循环,如若不然,可以将这三个循环执行三遍,则不用管i,j,k的顺序
代码示例
1 |
|