输入我们的当前位置和目的地,在线地图就可以推荐一些行进路线。
现在你的工作是向用户推荐两条路线:一条是最短路线,另一条是最快路线。
保证任何询问的两地之间都存在至少一条路线。
输入格式
第一行包含两个整数 N 和 M,表示地图中共有 N 个路口(编号 0∼N−1)和 M 个街道。接下来 M 行,每行描述一条街道,格式如下:
V1 V2 one-way length time
V1 和 V2 是两个路口的编号,表示这两个路口之间存在一条街道,one-way 如果为 1 则表示这条街道是单行道,只能从 V1 前往 V2。如果为 0 表示是双行道,可随意通行。 length 是街道的长度,time 是通过这条街道花费的时间。最后一行,将给出起点和终点路口的编号。
输出格式
第一行输出路程最短的路线,并输出最短路程 D,格式如下:Distance = D: source -> v1 -> ... -> destination
第二行输出用时最快的路线,并输出最短用时 T,格式如下:Time = T: source -> w1 -> ... -> destination
如果最短路线不唯一,则输出用时最短的那条路线(保证唯一)。如果最快路线不唯一,则输出经过路口最少的那条路线(保证唯一)。
如果最短路线和最快路线经过的路口序列完全相同,则以如下格式将两个信息输出在一行:
Distance = D; Time = T: source -> u1 -> ... -> destination
数据范围
2≤N≤500,
1≤M≤N(N−1)2,
每条道路的长度和用时都不超过 1000。
任意两个路口之间可能出现重复街道。(这一点和官网不同)输入样例1:
10 15
0 1 0 1 1
8 0 0 1 1
4 8 1 1 1
3 4 0 3 2
3 9 1 4 1
0 6 0 1 1
7 5 1 2 1
8 5 1 2 1
2 3 0 2 2
2 1 1 1 1
1 3 0 3 1
1 4 0 1 1
9 7 1 3 1
5 1 0 5 2
6 5 1 1 2
3 5
输出样例1:
Distance = 6: 3 -> 4 -> 8 -> 5
Time = 3: 3 -> 1 -> 5
输入样例2:
7 9
0 4 1 1 1
1 6 1 1 3
2 6 1 1 1
2 5 1 2 2
3 0 0 1 1
3 1 1 1 3
3 2 1 1 2
4 5 0 2 2
6 5 1 1 2
3 5
输出样例2:
Distance = 3; Time = 4: 3 -> 2 -> 5
我的解法:
#include <bits/stdc++.h>
using namespace std;
const int N = 510;
int n, m, dist[N], dist_ext[N];
int d1[N][N], d2[N][N];
int S, T;
bool st[N];
int pre[N];
pair<int, string> dijkstra(int d1[][N], int d2[][N], int type){
memset(dist, 0x3f, sizeof dist);
memset(dist_ext, 0x3f, sizeof dist_ext);
memset(st, 0, sizeof st);
dist[S] = 0, dist_ext[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 ++ ){
int w;
if(type == 0){
w = d2[t][j];
}
else w = 1;
if(dist[j] > dist[t] + d1[t][j]){
pre[j] = t;
dist[j] = dist[t] + d1[t][j];
dist_ext[j] = dist_ext[t] + w;
}
else if(dist[j] == dist[t] + d1[t][j]){
if(dist_ext[j] > dist_ext[t] + w){
pre[j] = t;
dist_ext[j] = dist_ext[t] + w;
}
}
}
}
pair<int, string> res;
res.first = dist[T];
res.second = to_string(S);
vector <int> path;
for(int i = T; i != S; i = pre[i]){
path.push_back(i);
}
for(int i = path.size() - 1; i >= 0; i -- ){
res.second += " -> " + to_string(path[i]);
}
return res;
}
int main(){
memset(d1, 0x3f, sizeof d1);
memset(d2, 0x3f, sizeof d2);
cin >> n >> m;
while(m -- ){
int a, b, t, c, d;
cin >> a >> b >> t >> c >> d;
d1[a][b] = min(d1[a][b], c);
d2[a][b] = min(d2[a][b], d);
if(!t){
d1[b][a] = min(d1[b][a], c);
d2[b][a] = min(d2[b][a], d);
}
}
cin >> S >> T;
auto res1 = dijkstra(d1, d2, 0);
auto res2 = dijkstra(d2, d1, 1);
if(res1.second != res2.second){
printf("Distance = %d: %s\n", res1.first, res1.second.c_str());
printf("Time = %d: %s", res2.first, res2.second.c_str());
}
else{
printf("Distance = %d; Time = %d: %s",res1.first, res2.first, res2.second.c_str());
}
return 0;
}
收获:
最短路径的“路径”不一定只有路径,这里强调的是最少的概念,也可以是最少时间
由于本题要求最短路径(路径不唯一取最短时间)和最短时间(路径不唯一取最少节点),所以需要两次dijkstra(),我们可以为函数设置参数type,根据type类型设置额外条件w的内容。对于最短路径,w为时间;对于最短时间,w为1(结点数)。