Bellman-Ford算法

Bellman-ford算法是求含负权的单源最短路径算法,效率很低,但代码很容易写。即进行不停地松弛(原文是这么写的,为什么要叫松弛,争议很大),每次松弛把每条边都更新一下,若n-1次松弛后还能更新,则说明图中有负环,无法得出结果,否则就成功完成。

Bellman-ford算法有一个小优化:每次松弛先设一个旗帜flag,初值为FALSE,若有边更新则赋值为TRUE,最终如果还是FALSE则直接成功退出。Bellman-ford算法浪费了许多时间做无必要的松弛


Dijkstra算法中不允许边的权是负权,如果遇到负权,则可以采用Bellman-Ford算法。


Bellman-Ford算法描述:
1,.初始化:将除源点外的所有顶点的最短距离估计值 d[v] ←+∞, d[s] ←0;

2.迭代求解: 进行循环,循环下标为从1到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进行更新,说明最短路径已经查找完毕,或者部分点不可达,跳出循环。否则执行下次循环;


3.检验负权回路: 为了检测图中是否存在负环路,即权值之和小于0的环路。对于每一条边e(u, v),如果存在Distant[u] + w(u, v) < Distant[v]的边,则图中存在负环路,即是说图无法求出单源最短路径。否则数组Distant[n]中记录的就是源点s到各顶点的最短路径长度。

/*
* About:  Bellman-Ford算法
* Author: Tanky Woo
* Blog:   www.WuTianqi.com
*/
 
#include 
< iostream >
using   namespace  std;
const   int  maxnum  =   100 ;
const   int  maxint  =   99999 ;
 
//  边,
typedef  struct  Edge{
    
int  u, v;     //  起点,重点
     int  weight;   //  边的权值
}Edge;
 
Edge edge[maxnum];     
//  保存边的值
int   dist[maxnum];      //  结点到源点最小距离
 
int  nodenum, edgenum, source;     //  结点数,边数,源点
 
//  初始化图
void  init()
{
    
//  输入结点数,边数,源点
    cin  >>  nodenum  >>  edgenum  >>  source;
    
for ( int  i = 1 ; i <= nodenum;  ++ i)
        dist[i] 
=  maxint;
    dist[source] 
=   0 ;
    
for ( int  i = 1 ; i <= edgenum;  ++ i)
    {
        cin 
>>  edge[i].u  >>  edge[i].v  >>  edge[i].weight;
        
if (edge[i].u  ==  source)           // 注意这里设置初始情况
            dist[edge[i].v]  =  edge[i].weight;
    }
}
 
//  松弛计算
void  relax( int  u,  int  v,  int  weight)
{
    
if (dist[v]  >  dist[u]  +  weight)
        dist[v] 
=  dist[u]  +  weight;
}
 
bool  Bellman_Ford()
{
    
for ( int  i = 1 ; i <= nodenum - 1 ++ i)
        
for ( int  j = 1 ; j <= edgenum;  ++ j)
            relax(edge[j].u, edge[j].v, edge[j].weight);
    
bool  flag  =   1 ;
    
//  判断是否有负环路
     for ( int  i = 1 ; i <= edgenum;  ++ i)
        
if (dist[edge[i].v]  >  dist[edge[i].u]  +  edge[i].weight)
        {
            flag 
=   0 ;
            
break ;
        }
    
return  flag;
}
int  main()
{
    
// freopen("input3.txt", "r", stdin);
    init();
    
if (Bellman_Ford())
        
for ( int  i  =   1  ;i  <=  nodenum; i ++ )
            cout 
<<  dist[i]  <<  endl;
    
return   0 ;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值