思路:Bellman-Ford解决的是带权有向图的单源最短路径问题。图中可以存在负权值的边,而且有负环时可以检测出来。设图中共有v个结点,e条边。算法分为以下三步。1.初始化所有结点的前驱结点为-1(不存在),初始化所有结点的最短路径权值为INF(无穷大),将源点的最短路径权值设为0。2.对图中所有边进行v-1次松弛操作。3.如果图中还有边可以进行松弛,则表示有负环存在,返回false。所谓的松弛操作是指,对于边(u,v),如果dis[v]>dis[u]+w(u,v),则dis[v]=dis[u]+w(u,v)。其中dis表示最短路径权值,w表示边的权值。
代码:
// bellman_ford.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <fstream>
#include <stack>
#define MAX 100
#define INF 1000000
using std::cin;
using std::cout;
using std::endl;
using std::cerr;
using std::vector;
using std::ifstream;
using std::stack;
typedef struct Edge {
int u;
int v;
int val;
};
//对边(u,v)的松弛操作
void relax(int u, int v, int dis[MAX], int pre[MAX], Edge edge[MAX], int index)
{
if (dis[v] > dis[u] + edge[index].val)
{
dis[v] = dis[u] + edge[index].val;
pre[v] = u;
}
}
bool bellman_ford(Edge edge[MAX], int vertex_num, int edge_num, int dis[MAX], int pre[MAX])
{
//n-1次松弛操作
for (int i = 0; i < vertex_num - 1; i++)
for (int j = 0; j < edge_num; j++)
relax(edge[j].u, edge[j].v, dis, pre, edge, j);
for (int i = 0; i < edge_num; i++)
if (edge[i].v > edge[i].u + edge[i].val)
return false;
return true;
}
//重构路径
void reconstruct(int i, int pre[MAX], stack<int> &s)
{
if (pre[i] == -1) //边界情况,重构源结点
{
s.push(i);
return;
}
s.push(i); //加入本结点
while(pre[i]!=-1)
{
s.push(pre[i]);
i = pre[i];
}
}
int main()
{
ifstream in;
in.open("bellman_ford测试数据.txt");
int vertex_num, edge_num; //点数,边数
in >> vertex_num >> edge_num;
Edge edge[MAX];
int u, v, val;
for (int i = 0; i < edge_num; i++)
{
in >> u >> v >> val;
edge[i].u = u;
edge[i].v = v;
edge[i].val = val;
}
int dis[MAX]; //最短路径权重
for (int i = 0; i < vertex_num; i++)
dis[i] = INF;
int pre[MAX]; //前驱结点
for (int i = 0; i < vertex_num; i++)
pre[i] = -1;
dis[0] = 0;
bellman_ford(edge, vertex_num, edge_num, dis, pre);
stack<int> s; //用于重构路径
for (int i = 0; i < vertex_num; i++)
{
cout << dis[i] << endl << "route: ";
reconstruct(i, pre, s);
while (!s.empty())
{
int temp = s.top();
cout << temp << " ";
s.pop();
}
cout << endl;
}
system("pause");
return 0;
}
运行结果: