经典最短路算法的原理启示
算法其实都差不多了,更重要的是对算法本身的理解,而不是根据题目去熟悉算法
floyd代码极其简短,只有几行:
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
for(k=1;k<=n;k++)
{if(i==j||j==k||k==i)continue;f[j][k]=min(f[j][i]+f[i][k],f[j][k]);
}
但这是不是说明代码短,可以记住,就可以不动脑子直接用?
如果直接用,而不去了解它的原理、精妙之处,那你就只学会了求最短路,而舍弃了一种思维方式,,况且,它还有很多变种、、
板子选手的生存环境越来越恶劣、
所以这看似比模拟还要短的代码里,有远比代码量有多得多的智慧
首先,图的最短路径问题具有递推的性质:
一条最短路径的子路径也是一条最短路径
因为从搜索的角度出发,它实际上是一种合并的过程:
对于每两对点,显然最短路径是唯一的(等价考虑为一种),所以,对于一条边,它只会从一个原点走一次。
显然,我们需要从若干条搜索的路径中选出一条。
对于从起点到达的一个点,它之后的选择是确定的,所以,我们需要取从起点到该点的最短路径
然后结合递推的思想,我们就可以自己构造最短路径的求法:
1、每次都对每一个节点的上一步取最小值,一直取顶点个数次,每进行一次,就会得到每一层的答案 (bellman-ford)
2、从起点分层,每一层找到一个更小的就从那一层更新这一条路,这是利用了搜索+更新的方法,节省了后面搜索的时间(dijkstra)
3、如果我们已经知道这个点之后会被更新,那我们就不用再一次更新这个点了(spfa)
所以如果我们能够发现、判断一些特点,算法是可以自己想出的、
所以求最短路,实际上用了最优子结构、分层、松弛、合并等经典思想,提升对这些思想的理解是可以延伸到很多难题的。
比如,
一、让你求一个最长路(不含环): 1、最长路径唯一 2、最优子结构 所以直接取最大值即可
二、让你判断/求一个负权环: 1、负权环最短路径是负无穷,所以,如果取最优子结构,则永远取不完。
所以:不含环的最短路一定是一条,而含环的最短路一定有环,,所以再求最短路时,记录前继,更新时判断是否是当前最短路的前继即可,,判断的话只需记录更新次数
三、让你求次短路: 次短路一定是比最短路差一个弯,所以我们只需更新两个值即可
四、让你求经过k条边的最短路: 每一次更新都是 被更新点的路径=上一个点+1 所以我们只需再开一个数组记录经过1~k条边的最短路即可
五、删掉一条边,使最短路尽量大。 首先,要删除的边一定在最短路上,所以容易想到每次枚举删一条边,跑最短路,但这样做是v^2e
所以可以:因为我们只删一条边,所以可以记录次短路,从起点到终点再跑一次 然后枚举每一条最短路边
当然这些算法都比较直观,floyd可能会比较难理解
对于最短路问题,可以这样想:每一次更新,都是通过另一条路径到达了相同的地方
所以:
可以算出每个点走一次的最短路,来更新走两次的最短路,在更新走3~4次的最短路
化成一条链,就是经典的区间dp模型:
但floyd有很大的不同,它第一步只能更新过这个点的路径,但并不能保证它最短,相邻两个点的最短路有可能是最后一次循环才确定的
所以,它的阶段就是只枚举一遍中间点,合并所有过这个点的路径,即找出所有点对的经过这个点的最短距离
网上有一种理解:
主要思想就是先找简化版的模型,然后再往外扩,看原来的方法是否可行,如果不可行是哪些地方不可行。
如这三重循环,实际上有两种作用:1、合并 2、更新
合并是指将两条路合成一条路, 即dis【i,j】=dis【i,k】+dis【k,j】 ,dis【i,j】之前是inf,作用是联通两个图;
更新是指通过另一条路更近 即dis【i,j】=dis【i,k】+dis【k,j】 ,dis【i,j】之前有一条路,但不如ikj更优
这样更新每个中间点,其相邻的点也都被连接,所以在跑完所有点后,所有的路径都会被便历到,
所以,当我们得到一条路径时,它可能会被另一条路径更新,并且我们可以放心的走更小路径(最优子结构)
所以对于floyd便历到的取值情况,我们只需选择较小的,这样一定是正确的(代表这两条路径都试过,不会有遗漏)
所以,它就是一个包含枚举思想的合并过程,这种枚举+最优合并的思想非常常见。
还有一个顺序问题:作为中间点的循环必须在最外层
因为如果把它放在里面,那就相当于对每两个点都扫一遍中间点,而每个点对之间只会被算一次
放在外层是为了保证每一次都能连通至少两个点,而放在内层则有可能发生两个点无论如何也更新不到的情况
所以只能放在最外层
可以看出,对于求解最短路的算法中,都牢牢抓住了一个性质——最优子结构 所以,这些算法都是基于dp的算法
对于一个问题,如果有一个比较巧妙的性质或结论,那这个题就是所谓的难题,所谓的不会做只是没有充分利用题目信息
对于性质的挖掘需要丰富自己的思维角度,从而形成一种直觉 或 通过进行简化、模拟,尝试找出重复与多余
所以解这些题需要自己的思考,通过思考中的点滴来形成有效的积累 , 有意识 地培养分析题目特点的能力、 善于变化,才能以不变胜万变。
经典最短路算法的原理启示相关推荐
- 最短路算法 算法 python实现
Dijkstra 算法[python] Dijstra作为一种经典的单源最短路算法,得到了广泛应用. 算法思想如下: 说明: S为最短路顶点集合 U为尚未加入S的顶点集合 cijc_{ij}cij表 ...
- dijkstra算法matlab程序_编程习题课 | 用最短路算法为你的小地图导航
简介:路网拓扑的正确导入方式,运筹学算法的完整实战案例,最详细的代码讲解与分享. 引言:在研究路径选择和流量分配等交通问题时,常常会用到最短路算法.用最短路算法解决交通问题存在两个难点:一.算法的选择 ...
- PageRank算法--从原理到实现
本文将介绍PageRank算法的相关内容,具体如下: 1.算法来源 2.算法原理 3.算法证明 4.PR值计算方法 4.1 幂迭代法 4.2 特征值法 4.3 代数法 5.算法实现 5.1 基于迭代法 ...
- DCT算法的原理及实现简介
DCT算法的原理及实现简介 DCT算法: DCT变换的全称是离散余弦变换(Discrete Cosine Transform),离散余弦变换相当于一个长度大概是它两倍的离散傅里叶变换,这个离散傅里叶变 ...
- 【机器学习入门】图解超经典的KNN算法
出品:Python数据之道(ID:PyDataLab) 作者:Peter,来自读者投稿 编辑:Lemon 图解超经典的KNN算法 本文中介绍的机器学习算法中的一种监督学习的算法:KNN 算法,全称是 ...
- 4个mos管驱动的全桥电路原理_最经典MOS管电路工作原理及详解没有之一
欢迎加入技术交流QQ群(2000人):电力电子技术与新能源 1105621549 高可靠新能源行业顶尖自媒体 在这里有电力电子.新能源干货.行业发展趋势分析.最新产品介绍.众多技术达人与您分享经验,欢 ...
- python用tsne降维_哈工大硕士实现了 11 种经典数据降维算法,源代码库已开放
网上关于各种降维算法的资料参差不齐,同时大部分不提供源代码.这里有个 GitHub 项目整理了使用 Python 实现了 11 种经典的数据抽取(数据降维)算法,包括:PCA.LDA.MDS.LLE. ...
- halcon机器视觉算法原理与编程实战_快速弄懂机器学习里的集成算法:原理、框架与实战...
作者: 博观厚积 简书专栏:https://www.jianshu.com/u/2f376f777ef1 1. 关于集成学习算法 集成学习算法,通俗地讲就是:三个臭皮匠,顶个诸葛亮,这在很多地方都有 ...
- 疯子的算法总结(八) 最短路算法+模板
Dijkstra:适用于权值为非负的图的单源最短路径,用斐波那契堆的复杂度O(E+VlgV) BellmanFord:适用于权值有负值的图的单源最短路径,并且能够检测负圈,复杂度O(VE) SPFA: ...
最新文章
- js 输出中文乱码 解决办法
- hive 时间转字符串_07697.0.3如何在Kerberos环境下用Ranger完成对Hive的行过滤及列脱敏...
- The hierarchy of the type is inconsistent
- ImageMagick还是GraphicsMagick?
- solr-4.10.3.tgz.tgz下载
- Java流程控制语句的基本概念
- 防火墙在setup进入不了
- optenstack配置keystone
- gradle脚本源码查看环境搭建
- 【图像分割】基于matlab GUI阙值+边缘检测+区域法图像分割【含Matlab源码 817期】
- 8 9区别 endnote7_大家都了解EndnoteX9这款软件吗
- vc red.msi matlab,vc red.msi x64+x32位版下载
- Moya、RxMoya基本使用
- 【DOORS】如何基于DOORS实施需求管理
- WCF 之 什么是WCF
- Linux下GL850G调试总结
- Pytorch中dim的理解
- python返回索引值_python 返回列表中某个值的索引方法
- java 打印机编程_JAVA实现连接本地打印机并打印文件的实现代码
- 基于JUNGO STACK的USB下载流程
热门文章
- TypeError: Unexpected keyword argument passed to optimizer: learning_rate解决方法
- 【文献学习】强化学习3:基于数据的方法
- c语言考试系统开发,基于WEB的(C语言)网络考试系统的开发与研究
- Spark shuffle:hash和sort性能对比
- 输出质数(java)
- python找数字程序_程序以查找Python中从1到N的所有缺失数字
- 拟牛顿法matlab程序_牛顿环实验的数据处理改进及图像分析
- python实现共轭梯度算法(含误差与运算次数的折线图)
- mysql st_contains实现_MySQL实现树状所有子节点查询的方法
- python抽奖滚动界面_Python使用Tkinter实现转盘抽奖器的步骤详解