Bellman-ford算法实现

      Bellman-ford算法是求解连通带权图中单源最短路径的一种算法,它允许图中存在权值为负的边。同时它还能够判断出图中是否存在一个权值之和为负的回路。如果存在的话,图中就不存在最短路径(因为,假设存在最短路径的话,那么我们只要将这条最短路径沿着权值为负的环路在绕一圈,那么这条最短路径的权值就会减少了,所以不存在最短的路径,因为路径的最小值为负无穷),如果不存在的话,那么求出源节点到所有节点的最短路径。它的基本思想是,进行n-1迭代,分别计算出从源节点到每一个节点的最多有k条边的路径(k是迭代的次数)。刚开始的时候是到源节点最多只有一条边的所有路径(有的节点可能和源节点不相邻,此时路径权值是MAXINT),然后对每一条边进行判断,看这条边是否将边的尾节点的的最短路径缩短了,也就是判断源节点到头结点的最短路径加上边的权值是不是比源节点到尾节点的当前路径的权值短。这样一直进行n-1次迭代。就找出了从源节点到所有的节点的最多有n-1条边的最短路径。最后再判断一次,如果此时还有更短的路径产生,那么图中就存在权值为负的环路。具体实现代码如下:

 

 

 

 /**

这边实现Bellman-ford算法, bellman-ford 算法就是不断的使用松弛技术

图使用邻接表表示,算法复杂度为:O(VE)

**/

 

#include <iostream>

using namespace std;

#define MAX_NODES             100000         //最大节点数

#define MAX_EDGES               100000        //最多的边数

#define MAX_DIST                   100000       //最长的可能路径 

 

class Edge

{

   //三个变量,头尾节点和边的权值

public:

   int head ,tail ;  

   double cost ;

   Edge (int head,int tail ,double cost):head(head),tail(tail),cost(cost){}

   Edge (){}

};

 

Edge* edges [MAX_EDGES] ;                               //用来存放边

double mindis[MAX_NODES];                          //用来存放每个节点的最短路径

int nodes;                                                             //实际的节点数

int edgenum;                                                       //图中的边数

int s ;                                                                      //源节点

 

//这边的默认的输入格式是节点数,边数,源节点,然后是所有的边(头尾节点,权值)

void   init()

{

    cin >> nodes >> edgenum >> s ;

for(int i =  0 ;i < nodes  ;i ++)

  mindis [i] = MAX_DIST;

       mindis [s]= 0;

    for(int i = 0 ;i < edgenum ;i++)

{

        int head,tail ;

double cost ;

cin >> head >> tail >> cost;

        edges[i] = new Edge(head,tail,cost);

if(head == s)

mindis [tail] = cost;

}

 

for(int i = 0 ;i < nodes ;i ++)

cout << mindis[i] <<"   " ;

cout << endl <<endl;

}

 

bool  bellman_ford()

{

bool changes = false;

    for(int i = 0 ; i < nodes ; i++)

{

        changes = false ;

for(int  j = 0 ; j < edgenum ; j ++)

{

  

               int head = edges[j]->head;                            //这边是j啊!!!!!!!!!!!!!!!

  int tail = edges[j]->tail;

  double cost = edges[j]->cost;

  // cout << (mindis[head] + cost) << "   " << head << "--head  " << mindis[tail] << endl;

                if((mindis[head] + cost )< mindis[tail])

{

                    mindis[tail] = mindis[head] + cost ;

changes = true ; 

}

}

}

return changes;

}

/**

测试数据

 

5

7

0

0 1 10

0 3 30

0 4 100

1 2 50

2 4 10

3 2 20

3 4 60

**/

int  main()

{

    init();

if(!bellman_ford())

for(int i = 0 ;i < nodes; i++)

cout << mindis [i] << endl;

 

return 0;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值