最短路径解决算法

本文详细介绍了最短路径算法,包括Dijkstra算法、Floyd算法和Bellman-Ford算法。Dijkstra算法不适用于负权边,而Floyd算法可以求解任意两点间最短路径,Bellman-Ford算法能处理负权边但效率较低。文章还探讨了这些算法的适用条件和优化策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.问题引入

        问题:从某顶点出发,沿图的边到达另一顶点(O(n2)Xn个,总体为3次方所经过的路

径中,各边上权值之和最小的一条路径——最短路径。解决最短路的问题有以下算

法,Dijkstra算法,Bellman-Ford算法,Floyd算法和SPFA算法,另外还有著名的启发式

搜索算法A*,不过A*准备单独出一篇,其中Floyd算法可以求解任意两点间的最短路径

的长度。笔者认为任意一个最短路算法都是基于这样一个事实:从任意节点A到任意

节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点到B。

二.Dijkstra算法

        该算法在《数据结构》课本里是以贪心的形式讲解的,不过在《运筹学》教材里被编排在动态规划章节,建议读者两篇都看看。

           image

        观察右边表格发现除最后一个节点外其他均已经求出最短路径。

        (1)   迪杰斯特拉(Dijkstra)算法按路径长度(看下面表格的最后一行,就是next点)递增次序产生最短路径。先把V分成两组:

  • S:已求出最短路径的顶点的集合
  • V-S=T:尚未确定最短路径的顶点集合

        将T中顶点按最短路径递增的次序加入到S中,依据:可以证明V0到T中顶点Vk的最短路径,或是从V0到Vk的直接路径的权值或是从V0经S中顶点到Vk的路径权值之和(反证法可证,说实话,真不明白哦)。

        (2)   求最短路径步骤

  1. 初使时令 S={V0},T={其余顶点},T中顶点对应的距离值, 若存在<V0,Vi>,为<V0,Vi>弧上的权值(和SPFA初始化方式不同),若不存在<V0,Vi>,为Inf。
  2. 从T中选取一个其距离值为最小的顶点W(贪心体现在此处),加入S(注意不是直接从S集合中选取,理解这个对于理解vis数组的作用至关重要),对T中顶点的距离值进行修改:若加进W作中间顶点,从V0到Vi的距离值比不加W的路径要短,则修改此距离值(上面两个并列for循环,使用最小点更新)。
  3. 重复上述步骤,直到S中包含所有顶点,即S=V为止(说明最外层是除起点外的遍历)。

        下面是上图的求解过程,按列来看,第一列是初始化过程,最后一行是每次求得的next点。

           image

        (3)   问题:Dijkstar能否处理负权边?(来自《图论》)

             答案是不能,这与贪心选择性质有关(ps:貌似还是动态规划啊,晕了),每次都找一个距源点最近的点(dmin),然后将该距离定为这个点到源点的最短路径;但如果存在负权边,那就有可能先通过并不是距源点最近的一个次优点(dmin'),再通过这个负权边L(L<0),使得路径之和更小(dmin'+L<dmin),则dmin'+L成为最短路径,并不是dmin,这样dijkstra就被囧掉了。比如n=3,邻接矩阵: 
0,3,4 
3,0,-2 
4,-2,0,用dijkstra求得d[1,2]=3,事实上d[1,2]=2,就是通过了1-3-2使得路径减小。不知道讲得清楚不清楚。

二.Floyd算法

        参考了南阳理工牛帅(目前在新浪)的博客。

        Floyd算法的基本思想如下:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点到B,所以,我们假设dist(AB)为节点A到节点B的最短路径的距离,对于每一个节点K,我们检查dist(AK) + dist(KB) < dist(AB)是否成立,如果成立,证明从A到K再到B的路径比A直接到B的路径短,我们便设置 dist(AB) = dist(AK) + dist(KB),这样一来,当我们遍历完所有节点K,dist(AB)中记录的便是A到B的最短路径的距离。

        很简单吧,代码看起来可能像下面这样:

for (int i=0; i<n; ++i) {
  for (int j=0; j<n; ++j) {
    for (int k=0; k<n; ++k) {
      if (dis
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值