3. Single-source shortest paths. The following is the adjacency matrix, vertex A is the source.
A B C D E
A -1 3
B 3 2 2
C
D 1 5
E -3
Bellman-Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题。对于给定的带权(有向或无向)图
G=(
V,E),其源点为
s,加权函数
w是 边集
E 的映射。对图
G运行
Bellman-Ford算法的结果是一个布尔值,表明图中是否存在着一个从源点
s可达的负权回路。若不存在这样的回路,算法将给出从源点
s到 图
G的任意顶点
v的最短路径
d[v]。
Bellman-Ford算法流程分为三个阶段:
(1) 初始化:将除源点外的所有顶点的最短距离估计值 d[v] ←+∞, d[s] ←0;
(2) 迭代求解:反复对边集E中的每条边进行松弛操作,使得顶点集V中的每个顶点v的最短距离估计值逐步逼近其最短距离;(运行|v|-1次)
(3) 检验负权回路:判断边集E中的每一条边的两个端点是否收敛。如果存在未收敛的顶点,则算法返回false,表明问题无解;否则算法返回true,并且从源点可达的顶点v的最短距离保存在 d[v]中。
#include <cstdlib>
#include <iostream>
#define N 5
#define MAX 9999
using namespace std;
struct Edge
{
int u, v, w;
};
Edge edge[MAX];
int d[N];
int vertex;
int BellmanFord()
{
bool flag = 1;
for(int i = 1; i < N; i++)
for(int j = 0; j < vertex; j++)
{
if(d[edge[j].v] > d[edge[j].u] + edge[j].w)
{
d[edge[j].v] = d[edge[j].u] + edge[j].w;
}
}
for(int j = 0; j < vertex; j++)
{
if(d[edge[j].v] > d[edge[j].u] + edge[j].w)
{
flag = 0;
break;
}
}
return flag;
}
void init()
{
memset(d, MAX, sizeof(d));
d[0] = 0;
cin >> vertex;
for(int i = 0; i < vertex; i++)
{
cin >> edge[i].u >> edge[i].v >> edge[i].w;
}
}
void print()
{
for(int i = 0; i < N; i++)
cout << d[i] << " ";
cout << endl;
}
int main(int argc, char *argv[])
{
init();
if(BellmanFord())
print();
else
cout << "exist negative circle" << endl;
system("PAUSE");
return EXIT_SUCCESS;
}
BellmanFord:可以解决带负权的单源最短路径问题,能够检测回路中的负权环。也常用于查分约束系统问题的求解。时间复杂度为 O(VE)。