给定一张地图,包含 N 个城市,M 条高速公路。
城市之间都能相互连通。
每条高速公路的长度和走该条公路的花费都是已知的,高速公路都是双向的。
现在要从地图中的某个城市前往另一个城市。
请你确定最短路径,当最短路径不唯一时,请你选取花费最小的路径(保证唯一)。
输入格式
第一行包含四个整数 N,M,S,D,分别表示城市数量,公路数量,起点城市编号,终点城市编号。城市编号从 0 到 N−1。
接下来 M 行,每行包含四个整数 a,b,c,d,表示城市 a 和城市 b 之间存在一条公路,长度为 c,花费为 d。
输出格式
共一行,首先输出从起点城市到终点城市的最短路径(花费最少的)经过的所有城市,然后输出最短路径的距离以及最小的花费。数据范围
1≤N≤500,
1≤M≤600,
1≤c,d≤500
输入样例:
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
输出样例:
0 2 3 3 40
我的解法:
#include <bits/stdc++.h>
using namespace std;
const int N = 550;
int n, m, S, T;
int g[N][N]; // 两节点的边长
int pre[N]; // 为了遍历输出路径,存储最短路当前节点的上一节点
int dist[N]; // 从S 到任一点的最短路径
int cost[N]; // 从S 到任一点最短路花费,如果有多条最短路,则是花费最少的最短路花费
int c[N][N]; // 两节点的花费
bool st[N]; // 是否使用过
void dijkstra(){
memset(dist, 0x3f, sizeof dist);
dist[S] = 0;
for(int i = 0; i < n; i ++ ){
int t = -1;
for(int j = 0; j <= n - 1; j ++ ){
if(!st[j] && (t == -1 || dist[j] < dist[t])){
t = j;
}
}
st[t] = true;
for(int j = 0; j <= n - 1; j ++ ){
if(dist[j] > g[t][j] + dist[t]){
dist[j] = g[t][j] + dist[t];
pre[j] = t;
cost[j] = cost[t] + c[t][j];
}
else if(dist[j] == g[t][j] + dist[t] && cost[j] > cost[t] + c[t][j]){
pre[j] = t;
cost[j] = cost[t] + c[t][j];
}
}
}
}
int main(){
cin >> n >> m >> S >> T;
memset(g, 0x3f, sizeof g);
memset(c, 0x3f, sizeof c);
while(m -- ){
int a, b, cc, dd;
cin >> a >> b >> cc >> dd;
g[a][b] = g[b][a] = min(g[a][b], cc);
c[a][b] = c[b][a] = min(c[a][b], dd);
}
dijkstra();
vector <int> path;
for(int i = T; i != S; i = pre[i] ){
path.push_back(i);
}
cout << S;
for(int i = path.size() - 1; i >= 0; i -- ){
cout << ' ' << path[i];
}
cout << ' ' << dist[T] << ' ' << cost[T];
return 0;
}
收获:
如何求出具体的最短路径,即输出最短路上的节点
用pre数组存取上一节点,遍历保存到vector里,最后再反向输出
for(int i = T; i != S; i = pre[i] ){
path.push_back(i);
}cout << S;
for(int i = path.size() - 1; i >= 0; i -- ){
cout << ' ' << path[i];
}