1507. 旅行计划
原题传送:AcWing 1507. 旅行计划
给定一张地图,包含 N N N 个城市, M M M 条高速公路。
城市之间都能相互连通。
每条高速公路的长度和走该条公路的花费都是已知的,高速公路都是双向的。
现在要从地图中的某个城市前往另一个城市。
请你确定最短路径,当最短路径不唯一时,请你选取花费最小的路径(保证唯一)。
输入格式
第一行包含四个整数 N , M , S , D N,M,S,D N,M,S,D ,分别表示城市数量,公路数量,起点城市编号,终点城市编号。
城市编号从 0 0 0 到 N − 1 N-1 N−1 。
接下来 M M M 行,每行包含四个整数 a , b , c , d a,b,c,d a,b,c,d ,表示城市 a a a 和城市 b b b 之间存在一条公路,长度为 c c c ,花费为 d d d 。
输出格式
共一行,首先输出从起点城市到终点城市的最短路径(花费最少的)经过的所有城市,然后输出最短路径的距离以及最小的花费。
数据范围
1
≤
N
≤
500
1 \le N \le 500
1≤N≤500 ,
1
≤
M
≤
600
1 \le M \le 600
1≤M≤600 ,
1
≤
c
,
d
≤
500
1 \le c,d \le 500
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
思路:
pre数组记录当前结点的上一个结点,最后逆序输出即可。
题解:
#include <bits/stdc++.h>
using namespace std;
const int N = 610;
int n, m, S, D;
int g[N][N], w[N][N];
int dist[N], cost[N], pre[N];
bool st[N];
void dijkstra()
{
memset(dist, 0x3f, sizeof dist);
memset(cost, 0x3f, sizeof cost);
dist[S] = 0, cost[S] = 0;
for(int i = 0; i < n; i++)
{
int t = -1;
for(int j = 0; j < n; j++)
if(!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
st[t] = true;
for(int j = 0; j < n; j++)
{
if(dist[j] > dist[t] + g[t][j])
{
dist[j] = dist[t] + g[t][j];
cost[j] = cost[t] + w[t][j];
pre[j] = t;
}
else if(dist[j] == dist[t] + g[t][j] && cost[j] > cost[t] + w[t][j])
{
cost[j] = cost[t] + w[t][j];
pre[j] = t;
}
}
}
}
int main()
{
scanf("%d%d%d%d", &n, &m, &S, &D);
memset(g, 0x3f, sizeof g);
memset(w, 0x3f, sizeof w);
while(m--)
{
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
g[a][b] = g[b][a] = min(g[a][b], c);
w[a][b] = w[b][a] = min(w[a][b], d);
}
dijkstra();
vector<int> path;
for(int i = D; i != S; i = pre[i])
path.push_back(i);
printf("%d", S);
for(int i = path.size() - 1; i >= 0; i--)
printf(" %d", path[i]);
printf(" %d %d", dist[D], cost[D]);
return 0;
}