这是章学勤的blog。Floyd算法为图中求最短路径的算法,但并不关心路径细节,百科上说只要稍加修改便可实现路径重建。但水平太次自己修改实现暂时有点难度,后来查了维基百科后发现有现成的解决方案,直接套用一下便可输出路径。标红处为与原算法的主要区别。第一张图片是解决的问题,接下来是输入的数据,然后是源代码,最后是结果。
10 14
0 1 2 3 4 5 6 7 8 9
0 1 45
0 2 35
0 3 50
1 2 20
1 5 90
1 8 70
2 4 50
3 4 50
5 6 20
5 7 50
5 8 50
6 0 40
6 3 40
9 8 35
#include<stdio.h>
#include<iostream>
#include<fstream>
#include<limits.h>
using namespace std;
#define INFINITY INT_MAX
#define MAX_VERTEX_NUM 10
typedef struct ArcCell {
int adj;
} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct {
int vexs[MAX_VERTEX_NUM];
AdjMatrix arcs;
int vexnum, arcnum;
} MGraph;
typedef struct {
bool path;
} PathCell, PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct {
int distance;
} DistanceCell, DistanceMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct {
int path;
} RecordCell, RecordMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
void CreateDG(MGraph &G);
void ShortestPath_FLOYD(MGraph G, PathMatrix &P, DistanceMatrix &D, RecordMatrix &record);
void getPath(RecordMatrix record, int v1, int v2);
int main() {
RecordMatrix record;
MGraph mg;
CreateDG(mg);
PathMatrix p;
DistanceMatrix d;
ShortestPath_FLOYD(mg, p, d, record);
cout << "请输入要求解的两个顶点的序列号" << endl;
int vertex1, vertex2;
cin >> vertex1;
cin >> vertex2;
if(d[vertex1][vertex2].distance == INFINITY) {
cout << "该地点无法到达" << endl;
return 0;
}
else printf("所求最短路径为:%d\n", d[vertex1][vertex2].distance);
cout << "经过路径为: ";
cout << vertex1 << " -> ";
getPath(record, vertex1, vertex2);
cout << vertex2 << endl;
}
void CreateDG(MGraph &G) {
ifstream cin("./graph.txt");
int v1, v2, w; //依次存放输入弧时,其所对应的顶点与权重
cout << "正在构造有向图" << endl;
cout << "请输入有向图的顶点数、弧数" << endl;
cin >> G.vexnum;
cin >> G.arcnum;
cout << "请依次输入每个顶点的值:" << endl;
for(int i=0; i<G.vexnum; ++i) cin >> G.vexs[i];
for(int i=0; i<G.vexnum; ++i)
for(int j=0; j<G.vexnum; ++j) {
if(i == j) G.arcs[i][j].adj = 0;
else G.arcs[i][j].adj = INFINITY;
}
cout << "请依次弧所依赖的两个顶点的序号及其权重" << endl;
for(int i=0; i<G.arcnum; ++i) {
cin >> v1;
cin >> v2;
cin >> w;
G.arcs[v1][v2].adj = w;
}
}
void ShortestPath_FLOYD(MGraph G, PathMatrix &P, DistanceMatrix &D, RecordMatrix &record) {
for(int v=0; v<G.vexnum; ++v) {
for(int w=0; w<G.vexnum; ++w) {
record[v][w].path = w;
D[v][w].distance = G.arcs[v][w].adj;
for(int u=0; u<G.vexnum; ++u) P[v][w][w].path = false;
if(D[v][w].distance < INFINITY)
P[v][w][v].path = P[v][w][w].path = true;
}
}
for(int u=0; u<G.vexnum; ++u)
for(int v=0; v<G.vexnum; ++v)
for(int w=0; w<G.vexnum; ++w)
if(D[v][u].distance+D[u][w].distance < D[v][w].distance && D[v][u].distance!=INFINITY && D[u][w].distance!=INFINITY) {
D[v][w].distance = D[v][u].distance+D[u][w].distance;
record[v][w].path = record[v][u].path;
for(int i=0; i<G.vexnum; ++i)
P[v][w][i].path = P[v][u][i].path || P[u][w][i].path;
}
}
void getPath(RecordMatrix record, int v1, int v2) {
int temp = record[v1][v2].path;
if(temp == v2) return;
cout << temp << " -> ";
getPath(record, temp, v2);
return;
}