1. 之前我们使用Dijstra算法可以求解出从源点到达其余顶点的最短距离,那么怎么样求解出源点到达v顶点最短距离中所经过的顶点呢?
2. 算法的执行过程如下:
① 其实也很简单,我们只需要在原来使用Dijstra算法求解最短距离的基础上增加上一个pre数组来记录从源点s到顶点v的最短距离中的前一个节点,这样当我们发现可以通过中间顶点u使得从源点s到顶点v的距离更短的时候可以记录从源点到达顶点v的最短路径上的前一个顶点
② 当Dijstra算法结束的时候,那么从源点s到其余顶点的最短距离中所经历的前一个顶点我们就记录下来了,但是我们只是求解出最短路径上每一个顶点的前驱,如何求解完整的路径呢?
pre[4] = 3;
pre[3] = 2;
pre[2] = 1;
pre[1] = 1;
当我们想知道起点v1到达v4的最短路径,就需要先从pre[4]得到v4的前驱节点v3,然后从pre[3]得到v3的前驱节点v2,再从pre[2]得到v2的前驱节点v1,其实这个就是一个递归的过程,不断使用pre的信息寻找前驱
3. 具体的代码如下:
#include<cstdio>
#include<iostream>
using namespace std;
const int maxSize = 1000;
const int INF = 100000000;
int n, m, s, G[maxSize][maxSize];
int d[maxSize];
bool vis[maxSize] = {false};
//pre[v]数组表示从起点到顶点v的最短路径上v的前一个顶点
int pre[maxSize];
void Dijstra(int s){
fill(d, d + maxSize, INF);
d[s] = 0;
for(int i = 0; i < n; i++){
int u = -1, min = INF;
for(int j = 0; j < n; j++){
if(vis[j] == false && d[j] < min){
u = j;
min = d[j];
}
}
if(u == -1) return;
vis[u] = true;
for(int v = 0; v < n; v++){
if(vis[v] == false && G[u][v] != INF && d[u] + G[u][v] < d[v]){
d[v] = d[u] + G[u][v];
pre[v] = u;
}
}
}
}
//输出源点到顶点v的最短路径
void shortPath(int s, int v){
if(s == v){
//相等的时候说明已经找到了第一个节点可以层层返回进行输出
cout << s << " ";
return;
}
shortPath(s, pre[v]);
cout << v << " ";
}
int main(void){
int u, v, w;
cin >> n >> m >> s;
//初始化的时候将每个顶点的前驱设置为自己
for(int i = 0; i < n; ++i) pre[i] = i;
fill(G[0], G[0] + maxSize * maxSize, INF);
for(int i = 0; i < m; i++){
cin >> u >> v >> w;
G[u][v] = w;
}
Dijstra(s);
for(int i = 0; i < n; i++){
cout << d[i] << " ";
}
// cout << endl;
//使用递归的方法来输出其中的最短路径
//输入v顶点
cin >> v;
// cout << s << " " << v << endl;
shortPath(s, v);
}