Bellman-Ford算法 单源最短路径(o(nm))

解决的问题依旧是找出A城市到B城市的最短路径

Bellman-Ford算法,找出各个顶点间的最短路径,路径权值可以是负数,但是不能存在负权回路(在这一回路中存在负权路径)。
而Dijkstra算法,是找出某个顶点到其它顶点的最短路径。当然Dijkstra也可以找出各个顶点间的最短路径,只要做n次Dijkstra就行了。

思路:
对每对顶点i、j,不断缩小i到j的最短路径的权。在i、j中加入顶点k,判断从i到k和k到j路径的和是否小于i到j的路径长度,如果是将k加入,并调整i到j的路径长度。

缩小的条件: a[i][j]>a[i][k]+a[k][j]; (a:每对顶点的路径长度)

下面两组测试数组,前一组没构成负权回路,后一组是负权回路,无法得出正确结果

第一组:

5
1 2 6
2 3 5
3 2 -2
5 3 -3
4 3 7
2 4 -4
5 4 9
1 5 7
4 1 2
2 5 8
0 0 0

第二组:

3
1 2 2
2 3 3
3 1 -8
0 0 0

 


#include<stdio.h>
#define MAX 10000
 
/*路径长度矩阵*/
int a[ 100 ] [ 100 ] ;
/*路径后继矩阵*/
int path[ 100 ] [ 100 ] ;
/*路径权值矩阵*/
int c[ 100 ] [ 100 ] ;
 
void Floyd( int n)
{
int i,j,k;
/*初始化a,path*/
for ( i= 1 ; i<= n; ++ i)
{
for ( j= 1 ; j<= n; ++ j)
{
if ( c[ i] [ j] ! = MAX)
{
path[ i] [ j] = j;
}
else
{
path[ i] [ j] = - 1 ;
}
a[ i] [ j] = c[ i] [ j] ;
}
}
/*尝试将顶点k扩充到已求得的从i到j的最短路径p上*/
for ( k= 1 ; k<= n; ++ k)
{
for ( i= 1 ; i<= n; ++ i)
{
for ( j= 1 ; j<= n; ++ j)
{
if ( a[ i] [ j] > a[ i] [ k] + a[ k] [ j] )
{
/*修改路径长度*/
a[ i] [ j] = a[ i] [ k] + a[ k] [ j] ;
/*修改路径*/
path[ i] [ j] = path[ i] [ k] ;
}
}
}
}
}
 
/*判断是否是负权回路*/
int isNegationLoop( int n)
{
int i,j,k;
for ( k= 1 ; k<= n; ++ k)
{
for ( i= 1 ; i<= n; ++ i)
{
for ( j= 1 ; j<= n; ++ j)
{
/*如果存在顶点k,从i到j存在一条更短的路径,则构成负权回路*/
if ( a[ i] [ j] > a[ i] [ k] + a[ k] [ j] )
{
return 0 ;
}
}
}
}
return 1 ;
}
 
/*打印各对顶点的路径情况*/
void Print( int n)
{
int i,j,next;
for ( i= 1 ; i<= n; ++ i)
{
for ( j= 1 ; j<= n; ++ j)
{
/*naxt为path的后续顶点*/
next= path[ i] [ j] ;
if ( next== - 1 )
{
printf ( "%d - %d no path/n " ,i,j) ;
}
else
{
/*每对顶点i、j的路径长度*/
printf ( "%d " ,a[ i] [ j] ) ;
printf ( "%d " ,i) ;
while ( next! = j)
{
printf ( "-> %d " ,next) ;
/*继续找下一后续顶点*/
next= path[ next] [ j] ;
}
printf ( "-> %d/n " ,j) ;
}
}
}
}
 
int main( )
{
int n,i,j,x,y,value;
scanf ( "%d" ,& n) ;
/*初始化c*/
for ( i= 0 ; i<= n; ++ i)
{
for ( j= 0 ; j<= n; ++ j)
{
if ( i== j)
{
c[ i] [ j] = 0 ;
}
else
{
c[ i] [ j] = MAX;
}
}
}
while ( 1 )
{
/*读入权值*/
scanf ( "%d%d%d" ,& x,& y,& value) ;
if ( x== 0 && y== 0 && value== 0 )
{
break ;
}
c[ x] [ y] = value;
}
Floyd( n) ;
if ( isNegationLoop( n) )
{
Print( n) ;
}
else
{
printf ( "the short loop isn't exit/n " ) ;
}
system ( "pause" ) ;
return 0 ;
}
    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/paul08colin/article/details/5769812
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞