AT_abc232_g Modulo Shortest Path
有趣题。
考虑最短路径 \(S=[S_1,S_2,\cdots,S_k]\),那么代价是 \(\sum ((a_{S_i}+b_{S_{i+1}})\bmod M)\)。
考虑 \(a_i\leftarrow (M-a_i)\bmod M\),那么 \((b_{S_{i+1}}-a_{S_i})\bmod M\) 实际上就是有向环上的距离,而 \(B\to A\) 就是 \(B\) 可以免费跳到 \(A\)。
建图跑最短路即可。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int> ;
template <typename T> bool Chkmin(T &x, T y) { return (x > y) ? (x = y, 1) : 0; }
const int kN = 4e5 + 5;
int n, m, tot;
int a[kN], b[kN], t[kN];
ll dis[kN];
bool vis[kN];
vector<pii> g[kN];
void AddEdge(int u, int v, int w) {
g[u].emplace_back(v, w);
}
void Dijkstra(int s) {
memset(dis, 0x3f, sizeof(dis));
priority_queue<pair<ll, int>> q;
q.emplace(dis[s] = 0, s);
while(q.size()) {
int x = q.top().second; q.pop();
if(vis[x]) continue;
vis[x] = 1;
for(pii k : g[x]) {
int to, w;
tie(to, w) = k;
if(Chkmin(dis[to], dis[x] + w)) q.emplace(-dis[to], to);
}
}
}
int main() {
// freopen("1.in", "r", stdin);
// freopen("1.out", "w", stdout);
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> a[i], a[i] = t[++tot] = (m - a[i]) % m;
for(int i = 1; i <= n; i++) cin >> b[i], t[++tot] = b[i];
sort(t + 1, t + tot + 1);
tot = unique(t + 1, t + tot + 1) - t - 1;
for(int i = 1; i <= tot; i++) {
int nxt = i % tot + 1;
AddEdge(i, nxt, (t[nxt] + m - t[i]) % m);
}
int p1 = 0, pn = 0;
for(int i = 1; i <= n; i++) {
int pa = lower_bound(t + 1, t + tot + 1, a[i]) - t;
int pb = lower_bound(t + 1, t + tot + 1, b[i]) - t;
AddEdge(pb, pa, 0);
if(i == 1) p1 = pa;
if(i == n) pn = pb;
}
Dijkstra(p1);
cout << dis[pn] << "\n";
return 0;
}
浙公网安备 33010602011771号