Codeforces2014E Rendez-vous de Marian et Robin(分层图最短路)
题意
组测试数据。
有一个旅行网络,由个点和 条边组成。第 条边连接顶点 、 ,从一端走到另一端需要花费时间 秒 (保证 是 偶数
)。玛丽安和罗宾需要选择在某个点相遇。玛丽安从顶点开始,罗宾从顶点 开始。
此外,个顶点中的 个顶点各有一匹马可用,玛丽安和罗宾都是优秀的骑手,可以在 秒内骑上马。骑马时,行进时间减半 (速度加倍)。一旦骑上某一匹马,就可以一直骑着它走完剩余的所有路程。相遇必须在顶点进行。任何一方都可以选择在任何顶点上等待对方。如果罗宾和玛丽安可以相遇,输出最早可以相遇的时间;否则,输出 -1
。
数据范围:
特别地,题目保证
题解
不难想到,可以枚举二者相遇的点
考虑以下三种情况:
Case
Case
Case
对于 Case
我们可以建一个如下的分层图,然后从起点和终点分别跑 Dijkstra
即可。
时间复杂度为:
点击查看代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
constexpr i64 inf = 1e18;
void solve() {
int n, m, h;
cin >> n >> m >> h;
vector<vector<pair<int, int>>> adj(2 * n);
for (int i = 0; i < h; i++) {
int a;
cin >> a;
a--;
adj[a].emplace_back(a + n, 0);
}
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
u--; v--;
adj[u].emplace_back(v, w);
adj[v].emplace_back(u, w);
adj[u + n].emplace_back(v + n, w / 2);
adj[v + n].emplace_back(u + n, w / 2);
}
auto dijkstra = [&](int s) {
priority_queue<pair<i64, int>, vector<pair<i64, int>>, greater<pair<i64, int>>> Q;
vector<i64> dist(2 * n, inf);
vector<bool> vis(2 * n, false);
dist[s] = 0LL;
Q.emplace(0LL, s);
while (!Q.empty()) {
int u = Q.top().second;
Q.pop();
if (vis[u]) {
continue;
}
vis[u] = true;
for (auto [v, w] : adj[u]) {
if (dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
Q.emplace(dist[v], v);
}
}
}
vector<i64> ans(n);
for (int i = 0; i < n; i++) {
ans[i] = min(dist[i], dist[i + n]);
}
return ans;
};
vector<i64> D1 = dijkstra(0), D2 = dijkstra(n - 1);
i64 ans = inf;
for (int i = 0; i < n; i++) {
ans = min(ans, max(D1[i], D2[i]));
}
if (ans == inf) {
// 无法相遇
ans = -1;
}
cout << ans << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步