#include <iostream>
using namespace std;
const int vertexNum = 5; //定义有向图的顶点个数
const int edgeNum = 10; //定义有向图的边数
const int INFINITE = 100000; //定义无穷大的大小
struct Edge { //边结构
int start; //边的起点
int end; //边的终点
int weight; //边的权值
};
struct Vertex { //顶点结构
int d; //源点到该结点的最短路径估计
int p; //该结点在最短路径树中的前驱结点
};
//程序只测试书中的一个测试用例,为方便起见,将顶点数组和边数组定义为全局变量
Vertex V[vertexNum + 1]; //顶点数组
Edge E[edgeNum + 1]; //边数组
void insertEdge(int i, int start, int end, int weight) { //向边数组中插入边
E[i].start = start;
E[i].end = end;
E[i].weight = weight;
}
void initGraph() { //为方便比对结果,插入边的顺序与书中P379上松弛操作对边的处理次序相同
insertEdge(1, 2, 3, 5);
insertEdge(2, 2, 5, 8);
insertEdge(3, 2, 4, -4);
insertEdge(4, 3, 2, -2);
insertEdge(5, 5, 3, -3);
insertEdge(6, 5, 4, 9);
insertEdge(7, 4, 3, 7);
insertEdge(8, 4, 1, 2);
insertEdge(9, 1, 2, 6);
insertEdge(10, 1, 5, 7);
}
void initialize_Single_Source(int s) { //对最短路径估计和前驱结点进行初始化
for (int i = 1; i <= vertexNum; i++) {
V[i].d = INFINITE;
V[i].p = -1;
}
V[s].d = 0;
}
void relax(int u, int v, int w) { //松弛操作
if (V[u].d != INFINITE && V[v].d > V[u].d + w) {
V[v].d = V[u].d + w;
V[v].p = u;
}
}
void print() { //输出顶点的属性
cout << "每个顶点的最短路径估计依次如下:" << endl;
for (int i = 1; i <= vertexNum; i++) {
cout << V[i].d << " ";
}
cout << endl;
cout << "每个顶点的前驱结点依次如下:" << endl;
for (int i = 1; i <= vertexNum; i++) {
cout << V[i].p << " ";
}
cout << endl << endl;
}
bool bellman_Ford(int s) { //Bellman_Ford算法
initialize_Single_Source(s); //初始化
for (int i = 1; i < vertexNum; i++) { //对图的每条边进行vertexNUm-1次处理
cout << "== 第" << i << "轮:" << endl;
for (int j = 1; j <= edgeNum; j++) { //依次对每条边进行松弛操作
relax(E[j].start, E[j].end, E[j].weight);
}
print(); //输出每一轮松弛后的结果
}
for (int j = 1; j <= edgeNum; j++) { //对负权回路进行检查
if (V[E[j].end].d > V[E[j].start].d + E[j].weight) {
return false;
}
}
return true;
}
int main() {
initGraph();
if (bellman_Ford(1)) {
cout << "图中不存在可以从源结点到达的权重为负值的环路" << endl;
}
else {
cout << "图中存在可以从源结点到达的权重为负值的环路" << endl;
}
return 0;
}