题目描述
【问题描述】最短路径问题实际上是带权有向图(网)的一种应用,用Dijkstra算法求两个顶点间的最短路径。备注:输入的有向网信息中0表示不存在顶点到自身的弧,32767表示两个顶点之间不存在弧。
【输入形式】带权有向图(网)的顶点数及,有向图(网)的信息,出发顶点。
【输出形式】输出出发顶点到有向图(网)其余顶点间的最短路径长度及其路径。
【样例输入】
输入顶点数:
7
输入有向网的信息:
0 4 6 6 32767 32767 32767
32767 0 1 32767 7 32767 32767
32767 32767 0 32767 6 4 32767
32767 32767 2 0 32767 5 32767
32767 32767 32767 32767 0 32767 6
32767 32767 32767 32767 1 0 8
32767 32767 32767 32767 32767 32767 0
输入出发顶点:
0
【样例输出】
从0顶点出发的最短路径如下:
从顶点0到顶点1的路径长度为:4 路径为:0,1
从顶点0到顶点2的路径长度为:5 路径为:0,1,2
从顶点0到顶点3的路径长度为:6 路径为:0,3
从顶点0到顶点4的路径长度为:10 路径为:0,1,2,5,4
从顶点0到顶点5的路径长度为:9 路径为:0,1,2,5
从顶点0到顶点6的路径长度为:16 路径为:0,1,2,5,4,6
解题思路
初始化:将起点的距离设置为0,将其他节点的距离设置为无穷大。将所有节点标记为未访问状态。
选择节点:从未访问的节点中选择距离起点最近的节点,将其标记为已访问状态。
更新距离:对于与当前节点相邻的节点,计算从起点到这些节点的距离,并更新它们的距离值。如果新的距离值比原来的距离值更小,则更新距离值。
重复步骤2和3,直到所有节点都被访问过或者目标节点被访问到。
回溯路径:从终点开始回溯,沿着每个节点的最短路径找到起点。
源代码
#include <bits/stdc++.h>
using namespace std;
#define MAX 100
#define INF 32767
//迪杰斯特拉算法
void Dijkstra(int n, int v, int(*Edges)[100], int* dist, int* path) {
int visited[MAX] = { 0 }; //建立"S"数组
dist[v] = 0;
for (int i = 0; i < n; i++) {
int minDist = INF;
int u = 0;
for (int j = 0; j < n; j++) {
if (!visited[j] && dist[j] < minDist) {
minDist = dist[j];
u = j;
}
}
visited[u] = 1;
for (int k = 0; k < n; k++) {
if (!visited[k] && Edges[u][k] != INF && dist[u] + Edges[u][k] < dist[k]) {
dist[k] = dist[u] + Edges[u][k];
path[k] = u;
}
}
}
}
//反向输出path数组即路径(递归实现)
void printPath(int* path, int v, int u, int k) { //定义变量k防止最后多输出一个逗号
if (path[u] != -1 && v != u)
printPath(path, v, path[u], k + 1);
cout << u;
if (k != 0)
cout << ",";
}
int main() {
int n, v;
cout << "输入顶点数:" << endl;
cin >> n;
int Edges[MAX][MAX];
cout << "输入有向网的信息:" << endl;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> Edges[i][j];
if (Edges[i][j] == 0) //处理对角线
Edges[i][j] = INF;
}
}
cout << "输入出发顶点:" << endl;
cin >> v;
int dist[MAX], path[MAX];
for (int i = 0; i < n; i++) {
dist[i] = INF;
path[i] = -1;
}
Dijkstra(n, v, Edges, dist, path);
cout << "从" << v << "顶点出发的最短路径如下:" << endl;
for (int i = 0; i < n; i++) {
if (i == v || dist[i] == INF)
continue;
cout << " 从顶点" << v << "到顶点" << i << "的路径长度为:" << dist[i] << "\t" << "路径为:";
printPath(path, v, i, 0);
cout << endl;
}
system("pause");
return 0;
}
总结
图的经典算法