输入始发地和目的地,向用户推荐两条路径:一条是最短路径,另一条是最快路径。保证路径一定存在。
输入第一行给出两个正整数 N、M,分别是地图上街道交叉点的总数、街道数。接下来 M 行,每行以v1 v2 one-way length time
的格式描述一条街道。其中,v1 和 v2 是街道两端的索引(从 0 到 N-1),one-way 为 1,表示街道是从 v1 到 v2 的单向路;否则,表示街道是双向路;length 是街道的长度;time 就是通过街道的时间。最后一行给出了始发地和目的地。
对于每种情况,首先以Distance = D: source -> v1 -> ... -> destination
格式打印距离 D 的从源到目的地的最短路径。然后在下一行中以Time = T: source -> w1 -> ... -> destination
格式打印最快的路径。如果最短路径不是唯一的,请输出最短路径中最快的一条,保证这样的路径是唯一的。如果最快的路径不是唯一的,则输出经过最少交叉点的那条,保证这样的路径是唯一的。如果最短路径和最快路径相同,则以Distance = D; Time = T: source -> u1 -> ... -> destination
格式将它们打印在一行中。
用两次 Dijkstra+DFS 算法求出最短路径和最快路径,为了方便编码我在 Dijkstra 和 DFS 算法的参数中均有 index 这个参数,index==0 时表示求的是最短路径;index==1 时表示求的是最快路径。将两个路径存储在两个 vector 中,为了方便编码,也可以定义一个长度为 2 的 vector 的数组,下标为 0 存储最短路径,下标为 1 存储最快路径,比较两个路径,根据是否完全一致按要求输出。
#include <bits/stdc++.h>
using namespace std;
using gg = long long;
using agg3 = array<gg, 3>;
const gg MAX = 505;
struct Edge {
gg to, cost, time;
Edge(gg t, gg c, gg ti) : to(t), cost(c), time(ti) {}
};
vector<vector<Edge>> graph(MAX);
vector<gg> dis(MAX), dis2(MAX), past(MAX, -1);
vector<vector<gg>> path(2);
void Dijkstra(gg s, gg index) {
priority_queue<agg3, vector<agg3>, greater<agg3>> pq;
fill(dis.begin(), dis.end(), INT_MAX);
fill(dis2.begin(), dis2.end(), INT_MAX);
dis[s] = dis2[s] = 0;
pq.push({0, 0, s});
while (not pq.empty()) {
auto p = pq.top();
pq.pop();
if (dis[p[2]] != p[0]) {
continue;
}
for (auto& e : graph[p[2]]) {
gg v1 = index == 0 ? e.cost : e.time, v2 = index == 0 ? e.time : 1;
if (tie(dis[e.to], dis2[e.to]) > make_tuple(p[0] + v1, p[1] + v2)) {
dis[e.to] = p[0] + v1;
dis2[e.to] = p[1] + v2;
past[e.to] = p[2];
pq.push({dis[e.to], dis2[e.to], e.to});
}
}
}
}
void dfs(gg v, gg index) {
if (v == -1) {
return;
}
dfs(past[v], index);
path[index].push_back(v);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
gg ni, mi;
cin >> ni >> mi;
while (mi--) {
gg a, b, c, d, e;
cin >> a >> b >> c >> d >> e;
graph[a].push_back(Edge(b, d, e));
if (c == 0) {
graph[b].push_back(Edge(a, d, e));
}
}
gg s, e;
cin >> s >> e;
Dijkstra(s, 0);
dfs(e, 0);
gg len = dis[e];
Dijkstra(s, 1);
dfs(e, 1);
gg time = dis[e];
if (path[0] == path[1]) {
cout << "Distance = " << len << "; Time = " << time << ": ";
for (gg i = 0; i < path[0].size(); ++i) {
cout << (i == 0 ? "" : " -> ") << path[0][i];
}
} else {
cout << "Distance = " << len << ": ";
for (gg i = 0; i < path[0].size(); ++i) {
cout << (i == 0 ? "" : " -> ") << path[0][i];
}
cout << "\nTime = " << time << ": ";
for (gg i = 0; i < path[1].size(); ++i) {
cout << (i == 0 ? "" : " -> ") << path[1][i];
}
}
return 0;
}