dijkstra算法只能处理不带有负权边的图的单源最短的路问题,而Bellman_Ford算法则更一般,不仅能够处理带有负权边的图,而且能够在图中存在负权回路的时候返回出错信息。
/*===========================================================*\
* Bellman_Ford 2014.7.19_basement_boy
* 单源最短路,有向图无向图,边权可正可负(存在负权回路的话返回false)
* INIT:初始化边集edge[],无向边当作两条有向边处理
* 函数调用后,
* 返回值如果是true,说明不存在负权回路
* pre[]表示从源点到各个点路径的路径树
* dist[]表示从源点到各个点的最短路长度
\*===========================================================*/
struct Edge{ //边类型定义
int u,v; //起点和终点
int l; //边长-----------------------------******(可能是浮点型)
};
int n,m; //n是点数,m是边数
const int N=550,M=5500; //问题中给出的可能的最大点数和最大边数(无向边算两条边)-----------------*******(根据实际问题修改)
const int MAXL = 0x3f3f3f3f; //边的无限长
Edge edge[M+10]; //边集
int pre[N+10]; //从源点到该点的路径上该点的前驱(以源点为根的路径树,根结点的值为-1)
int dist[N+10]; //从源点到该点的最短距离
//松弛操作
bool relax( Edge e ){
if( dist[e.v] > dist[e.u]+e.l ){
dist[e.v] = dist[e.u]+e.l;
pre[e.v] = e.u;
return true; //进行更新的话返回真值
}
return false;
}
bool bellman(int s){
//初始化dist[] 和 pre[]
for(int i=0 ; i<n ; i++){
dist[i] = MAXL;
pre[i] = -1;
}
dist[s] = 0;
bool change = false; //使用标记优化,提高效率
for(int i=1 ; i<n ; i++){
change = false;
for(int j=0 ; j<m ; j++){
if( relax(edge[j]) )
change = relax;
}
if( !change ) //如果对所有边进行的一次relax()操作没有更新说明已经找到了到所有点的最短路
break;
}
for(int i=0 ; i<m ; i++){
if( relax(edge[i]) )
return false; //再对所有边进行一次relax()操作,如果有更新dist[]则说明存在负权回路
}
return true;
}