ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

No.6.3 最短路径之Bellman-Ford算法--解决负权边

2021-07-30 21:31:46  阅读:229  来源: 互联网

标签:10 -- 源点 Bellman Ford int 回路 负权 dis


一、无论Floyd还是Dijkstra,算法的假设前提就是,没有负权边。

但是Bellman-Ford算法可以:

  if( dis[v[i]] > dis[u[i]] + w[i])

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

  u[i], v[i], w[i] 分别记录一条边的起点,终点,边长;dis[x] 表示源点 1 到 顶点 x 的最短距离;

  那么算法的意思就是:如果通过顶点 u[i] 使得 源点 1 到 顶点 v[i] 的距离变短,那么执行Dijkstra的“松弛“操作!

过程:

  1.先按照给定边的顺序松弛,这时表示的是源点 1 ,只能经过一条边时,到达其他各点的最短路径;

  2.重复松弛,这时表示的是源点 1 ,经过 2<= k <= n-2 条边时(n个节点之间最多n-1条边,仅需松弛循环n-2次),可到达其他各点的最短路径;

  3.k>=n的可能性(回路):如果是正权回路,那么越走越远;如果是负权回路,则没有最短路径。所以不可能有最短路径中不可能有回路;

 

二、code

int main(){
  int i,j,n,m;
  int dis[10];
  int inf=999999;
  int u[10],v[10],w[10];

  scanf("%d %d",&n,&m); //n=点数,m=边数

  for(i=1;i<=m;i++){
    scanf("%d %d %d",&u[i],&v[i],&w[i]);
  }


  for(i=1;i<=n;i++)
    dis[i]=inf;
  dis[1]=0;

  for(i=1;i<=n-1;i++){     //Bellman-Ford 算法核心
    for(j=1;j<=m;j++){   //松弛的对象是边,不是点!
      if(dis[v[j]] > dis[u[j]] + w[j])
        dis[v[j]] = dis[u[j]] + w[j];
    }
  }

  //如果n-1轮松弛之后,最短路径依然会发生变化,说明该图存在负权回路!
  for(i=1;i<=m;i++)
    if(dis[v[i]] > dis[u[i]] + w[i])
      printf("图中存在负权回路");

  for(i=1;i<=n;i++)
    printf("%d\t",dis[i]);

  getchar();getchar();return 0;
}

算法的时间复杂度为O(NM),对于稀疏图来说,比Dijkstra要高效的多!

 

标签:10,--,源点,Bellman,Ford,int,回路,负权,dis
来源: https://www.cnblogs.com/yalimy/p/15082599.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有