貌似Bellman-Ford算法和Dijkstra算法类似,只是多了个处理负权值的考虑。不过Bellman-Ford算法比较简单易懂,虽然复杂度较高,有O(VE)。
算法类如下,至于介绍吧,维基(http://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm)上面蛮详细的。
三个步骤:
1、数组Distant[i]记录从源点s到顶点i的路径长度,初始化数组Distant[n]为无穷大, Distant[s]为0;
2、以下操作循环执行至多n-1次,n为顶点数:
对于每一条边e(u, v),如果Distant[u] + w(u, v) < Distant[v],则另Distant[v] = Distant[u]+w(u, v)。w(u, v)为边e(u,v)的权值;
若上述操作没有对Distant进行更新,说明最短路径已经查找完毕,或者部分点不可达,跳出循环。否则执行下次循环;
3、为了检测图中是否存在负环路,即权值之和小于0的环路。对于每一条边e(u, v),如果存在Distant[u] + w(u, v) < Distant[v]的边,则图中存在负环路,即是说改图无法求出单源最短路径。否则数组Distant[n]中记录的就是源点s到各顶点的最短路径长度。
#include <iostream>
#define POINTNUM 10
#define NOSET_POSITIVE_INT -1
#define INIFINITE 2147483647
using namespace std;
struct Edge
{
int source;
int destination;
int weight;
};
class Graph
{
public:
Edge graphEdge[POINTNUM * POINTNUM];
int edgeNum;
int pointNum;
int source;
int destination;
int distance[POINTNUM];
Graph();
bool BellmanFord();
private:
void initialize(); //Initialize the variables.
void relaxEdges(); //Relax the edges.
bool checkNegativeCycle(); //Check negative weight cycles.
};
Graph::Graph()
{
edgeNum = 0;
pointNum = 0;
source = NOSET_POSITIVE_INT;
destination = NOSET_POSITIVE_INT;
}
void Graph::initialize()
{
for (int i = 0; i < pointNum; i++)
{
distance[i] = INIFINITE;
}
distance[source] = 0;
}
void Graph::relaxEdges()
{
unsigned int a;
unsigned int b;
for (int i = 1; i < pointNum; i++)
{
for (int j = 0; j < edgeNum; j++)
{
a = (unsigned int)distance[graphEdge[j].source] + (unsigned int)graphEdge[j].weight;
b = (unsigned int)distance[graphEdge[j].destination];
if (a < b)
{
distance[graphEdge[j].destination] = a;
}
}
}
}
bool Graph::checkNegativeCycle()
{
unsigned int a;
unsigned int b;
for (int i = 0; i < edgeNum; i++)
{
a = (unsigned int)distance[graphEdge[i].source] + (unsigned int)graphEdge[i].weight;
b = (unsigned int)distance[graphEdge[i].destination];
if (a < b)
{
return false;
}
}
return true;
}
bool Graph::BellmanFord()
{
initialize();
relaxEdges();
return checkNegativeCycle();
}
int main()
{
Graph a;
cin >> a.edgeNum;
cin >> a.pointNum;
for (int i = 0; i < a.edgeNum; i++)
{
cin >> a.graphEdge[i].source >> a.graphEdge[i].destination >> a.graphEdge[i].weight;
}
cin >> a.source;
if( a.BellmanFord() )
{
for (int i = 0; i < a.pointNum; i++)
{
cout << "Distance: " << a.distance[i] << endl;
}
}
return 0;
}