2017/8/5训练日记(最短路径算法之Dijkstra算法和Bellman-Ford算法)

今天着重看了图论关于最短路径算法的实现

最短路径(两顶点之间经历的边上权值之和最短的路程)

具体的形式包括:

单源最短路和每对顶点的最短路问题

1.单源最短路径
bellman-ford算法
 spfa算法
 dijkstra算法

2.每对顶点的最短路径
 floyd-washall算法

关于单源的最短路径,还没看到spfa算法可能会看;下面附上bellman-ford算法和 dijkstra算法简单内容

Dijkstra算法:

Dijkstra算法能得出最短路径的最优解但遍历计算的节点多于是导致效率低

按路径长度递增次序产生算法:
把顶点集合V分成两组:
(1)S:已求出的顶点的集合(初始时只含有源点V0)
(2)V-S=T:尚未确定的顶点集合
将T中顶点按递增的次序加入到S中,保证:
(1)从源点V0到S中其他各顶点的长度都不大于从V0到T中任何顶点的最短路径长度
(2)每个顶点对应一个距离值
S中顶点:从V0到此顶点的长度
T中顶点:从V0到此顶点的只包括S中顶点作中间顶点的最短路径长度
依据:可以证明V0到T中顶点Vk的,或是从V0到Vk的直接路径的权值;或是从V0经S中顶点到Vk的路径权值之和

伪代码:

1. 初始化数组dist、path和s;
2. while (s中的元素个数<n)
     2.1 在dist[n]中求最小值,其下标为k;
     2.2 输出dist[j]和path[j];
     2.3 修改数组dist和path;
     2.4 将顶点vk添加到数组s中;

但Dijkstra算法有其缺陷性,那就是不能处理负权回路:

Dijkstra对于标记过的点就不再进行更新了,所以即使有负权导致最短距离的改变也不会重新计算已经计算过的结果
我们需要新的算法——Bellman-Ford

Bellman-Ford算法

流程如下:
给定图G(V, E)(其中V、E分别为图G的顶点集与边集),源点s,数组Distant[i]记录从源点s到顶点i的路径长度,初始化数组Distant[n]为, Distant[s]为0;
以下操作循环执行至多n-1次,n为顶点数:
对于每一条边e(u, v),如果Distant[u] + w(u, v) < Distant[v],则另Distant[v] = Distant[u]+w(u, v)。w(u, v)为边e(u,v)的权值;
若上述操作没有对Distant进行更新,说明最短路径已经查找完毕,或者部分点不可达,跳出循环。否则执行下次循环;
为了检测图中是否存在负环路,即权值之和小于0的环路。对于每一条边e(u, v),如果存在Distant[u] + w(u, v) < Distant[v]的边,则图中存在负环路,即是说改图无法求出单源最短路径。否则数组Distant[n]中记录的就是源点s到各顶点的最短路径长度。
步骤

第一,初始化所有点。每一个点保存一个值,表示从原点到达这个点的距离,将原点的值设为0,其它的点的值设为无穷大(表示不可达)。
第二,进行循环,循环下标为从1到n-1(n等于图中点的个数)。在循环内部,遍历所有的边,进行松弛计算。
第三,遍历途中所有的边(edge(u,v)),判断是否存在这样情况:
d(v) > d (u) + w(u,v)
则返回false,表示途中存在从源点可达的权为负的回路。
之所以需要第三部分的原因,是因为,如果存在从源点可达的权为负的回路。则 应为无法收敛而导致不能求出最短路径。 

区别

简单的说:
Dijkstra算法在求解过程中,源点到集合S内各顶点的最短路径一旦求出,则之后不变了,修改的仅仅是源点到T集合中各顶点的最短路径长度。
Bellman算法在求解过程中,每次循环都要修改所有顶点的dist[ ],也就是说源点到各顶点最短路径长度一直要到Bellman算法结束才确定下来。

今天可能a的代码比较少,但这两个算法我还在消化(QAQ),希望能更进一步吧,fighting!!

附带大佬有关图论这部分算法的博客:

http://blog.csdn.net/acm_1361677193/article/details/48211319

http://blog.csdn.net/niushuai666/article/details/6791765

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/qq_37748451/article/details/76708788
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞