zoukankan      html  css  js  c++  java
  • 最短路径问题 3.Bellman-Ford算法

    简要:Bellman-Ford算法计算的仍然是从一个点到其他所有点的最短路径算法,其时间复杂度是O(NE),N表示点数,E表示边数,不难看出,当一个图稍微稠密一点,边的数量会超过点数那么实际上效率是低于Dijkstra算法的。但是本算法可以计算存在负权边的情况(不存在负回路),因此可以用于更广泛的情况,但其实在日常解题应用中我们基本不会用到该算法,因为有一个比它效率更高的算法即SPFA算法,下一章会介绍到。SPFA算法其实是从Bellman-Ford算法演变而来的,那么从基础的开始,我们先来理解一下Bellman-Ford算法。

    算法描述:s为起点,dis[v]为s到v的最短距离,pre[v]是v的前驱结点,w[j]是边 j 的长度,j 边的起点和终点分别是u,v。

    1、初始化:dis[s]=0, dis[v]=∞(v≠s), pre[s]=0

    2、for(i=1;i<=n-1;i++)

           for(j=1;j<=e;j++)

             if(dis[u]+w[j]<dis[v]){

                dis[v]=dis[u]+w[j];

                pre[v]=u;

               }

    算法理解:一开始已标记的点只有起点,每一次枚举所有的边,总会有一些边连接着已标记的点和未标记的点,即已经计算过最短距离和为计算过最短距离的点。因此每次枚举都会更新一些未标记的点成为已标记的点。而n-1次则保证了最坏情况下所有的点均可以被标记,即图的样子是一“串”的情况。

    对于负权回路的情况,因为每一次枚举都会走过一圈负权回路,那么恰好在该回路两边的点之间的最短距离就会无限减小,因此会造成错误。对此,大家给出了一个不是解决方法的解决方法,就是如果在两重循环结束后,再次枚举每条边,如果再次出现某两点的距离减少,那么就返回"错误",已表示有负权回路,无法算出答案。

    当然,对于负权回路也有解决方法,在介绍完SPFA算法后会补充一下。

    代码如下:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    int n,e,s;
    struct node{
        int x;
        int y;
        int val;
    }m[105];
    int dis[105],pre[105],a,b,w[105][105];
    int bellmanford(int s){
         int i,j;
         
         for(i=1;i<=n;i++)
          dis[i]=w[s][i];
        dis[s]=0;pre[s]=0;
         for(i=1;i<=n-1;i++)
          for(j=1;j<=e;j++)
               if(dis[m[j].x]+m[j].val<dis[m[j].y])
               {
               dis[m[j].y]=dis[m[j].x]+m[j].val;
            pre[m[j].y]=m[j].x;    
               }
         for(j=1;j<=e;j++){
             if(dis[m[j].x]+m[j].val<dis[m[j].y]) return 0;
         }
         return dis[5];
             
    }
    int main(){
        int i,j;
        scanf("%d%d",&n,&e);
        memset(dis,100,sizeof(dis));
        memset(w,100,sizeof(w));
         for(i=1;i<=e;i++){
            scanf("%d%d%d",&m[i].x,&m[i].y,&m[i].val);
            a=m[i].x;
            b=m[i].y;
            w[a][b]=m[i].val;
        }
        for(i=1;i<=5;i++)
         for(j=1;j<=5;j++)
          printf("%d ",w[i][j]);
        scanf("%d",&s);
        printf("%d",bellmanford(s));
        return 0;
    } 
  • 相关阅读:
    CPU、io、mem之间的关系
    SSH交互式脚本StrictHostKeyChecking选项 benchmode=yes
    Linux学习笔记:fuser和lsof
    /proc/sys/kernel/sysrq /proc/sysrq-trigger----强制重启/触发器
    Android UI学习
    Android之TabHost布局(转)
    android AsyncTask介绍(转)
    android:imeOptions属性(转)
    Android:dimen尺寸资源文件的使用(转)
    解决Android解析图片的OOM问题!!!(转)
  • 原文地址:https://www.cnblogs.com/uncklesam7/p/8878006.html
Copyright © 2011-2022 走看看