最短路算法总结

Floyed-Warshall算法,是属于多源最短路径算法,是来计算任意两点之间的最短路径算法。这个算法核心代码就只有五行,基本思想是:最开始只允许经过1号顶点进行,接下来只允许经过1号和2号中转......允许经过1至n号顶点中转,用一句话概括就是,从i号顶点只经过前k号顶点的最短路程。算法结束之后,dis[i][j]存的就是从i到j的最短路径。比如想知道a点到b点的最短路,只能加入中间点来缩短路径,若a到b 之间加入中间点k ,a到k,k到b 那么我们可以这样判断,要知道i到j的最短路,我们只要判断e[i][j]是否大于e[i][1]+e[1][j]即可,而中间值1则要用for循环从1到n遍历一个遍,就是查找所有中间值。 Floyed-Warshall算法,还可以解决一些负权的边,比如这次的题目中有判断负权回路和判断正权回路。

Dijkstra算法,是属于单源最短路径算法,此算法用来计算从一个点到其他所有点的最短路径。但是不能处理存在负边权的情况。这个算法是属于贪心的思想,其中用到了几个数组,如dis数组用来储存起点到其他点的最短路,但开始时存的是起点到其他点的初始路程,也可以叫作估计值,通过n-1遍的遍历找最短。举个例子,1到3的最短路就是比较dis[3]与dis[2]+e[2][3],如果大于的话就更新dis[3]为dis[2]+e[2][3],有一个这个专业术语,叫松弛,这个算法的核心思想就是通过边来松弛起始点到其他点的路程,book数组用来标记,被标记的是已经找过的最短路,没被标记的没有被找过的最短路,当全部找过以后算法结束,也就是说dis数组中的数是起始点到其他所有点的最短路,就是确定值,算法结束后,dis[n]存的就是从起点到n点的最短路径。

还可以用邻接表来存储一个图,这种方法为每个顶点i(i从1到n)都设置了一个链表,边的信息用三个数组来存,如u[i],v[i],w[i],表示第i条边是从顶点第u[i]号顶点到v[i]号顶点,且权值为w[i],还用到了两个别样的数组,first数组用来存储1到n号顶点的第一条边的编号,next数组是用来存储编号为i的边的下一条边的编号。

Bellman-Ford算法,可以计算负权值。先说一下负权回路,如果是单向图,那么所有权值之和为负数,这是负权回路。如果是无向图只要有一个负权值,就不会存在最短路,跟负权回路一个意思。这个算法也是遍历n-1遍找所有的点,Dijkstra算法也是n-1次遍历,是因为有n-1个点需要遍历,这个也是因为最短路是一个不包含回路的路径,无论正负权回路都不能有,那么去掉回路,n个点任意两点之间就最多有n-1条边。但是程序可能在不到n-1次循环就已经找到了所有最短路,说明这个是最坏情况下是n-1次遍历。 dis数组同样存的是起始点到各个顶点的最短路,这个与Dijkstra不同的是,Dijkstra每次找到最近的点进行松弛操作,而这个Bellman则是只要路程更短就松弛。如果有负权值回路,那最短路就不会存在,因为最短路会越来越小。那么在n-1轮松弛后,要是还能松弛就代表存在负权回路。

队列优化的bellman,也叫spfa,spfa在形式上和广度优先搜索很像,不同的是广度优先搜索中的一个点出了队列就不可能重新进入队列,但是spfa中的一个点可能在出队列之后再次被放入队列,意思就是说一个点修改过其他的点之后,过了一段时间可能会获得更短的路径,于是再次用来修改其他的点,这样反复进行下去。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值