常见的最短路问题有哪些?
源点: 起点 汇点: 终点
边权: 离散数学或数据结构中,图的每条边上带的一个数值,他代表的含义可以是长度等等,这个值就是边权。
1.单源最短路 (只有一个起点)
求从一个点到其他所有点的最短距离,最常见的一个问题:从1号点到n号点的最短路
(1) 所有边权都是正数 (其中n为点的数量,m为边的数量)
朴素 Dijkstra 算法 时间复杂度 O(n^2) (如果是一个稠密图(存储用邻接矩阵),例如 m 和 n^2 是一个级别的就用朴素 Dijkstra 算法)堆优化版的 Dijkstra 算法 O(mlogn) (如果是一个稀疏图(存储用邻接表),例如 m 和 n 是一个级别的就用堆优化版的 Dijkstra 算法)(2)存在负权边(某些边的权重是负数)
Bellman-Ford 时间复杂度 O(mn) (如果说让我们求不超过k条边的最短路,用 Bellman-Ford 算法比较好)SPFA 一般情况下时间复杂度:O(m) ,最坏的情况下是:O(mn) SPFA算法是 Bellman-Ford 算法的优化。2.多源汇最短路 (有很多个不同的起点)
Floyd 算法 O(n^3)最短路算法常见的考察方法:
原理:
(1) Dijkstra 算法基于贪心 (2) Floyd 算法基于动态规划 (3) Bellman-Ford 算法基于离散数学的知识难点:建图。
一般是,给一个问题,让抽象出来建图。
朴素 Dijkstra 算法
主要思想:每次找到离源点最近的一个顶点,然后以该点为中转点进行扩展( 看其余点到源点的距离是否能通过当前中转点到源点的最短距离加上中转点到该点的距离来更新其到源点的最短距离 ),最终找到源点到其余所有点的最短路径
① 初始化距离
让dis[1] = 0;// 1号点到起始点的距离是0
dis[其它所有] = +∞ // 让其他点到起点的距离为 +∞
② 是一个迭代的过程 (set{s}:元素为当前已经确定了最短路的点,放到集合s里面)
for(0~n) 1.在迭代的过程中找到不在s中的最短距离的点,赋值给t 2.把t放到集合s里面去 n次 3.用t更新其它所有点的距离(看一下dis[t] + w(权重) 与 dis[x],如果dis[x] > dis[t] + w,就可以用t更新其它点的距离)m次