#2350. 「JOI 2018 Final」月票購買
阿新 • • 發佈:2020-11-22
先跑一遍 \(s,t,u,v\) 的單源最短路,然後可以免費的路徑是 \(s\) 到 \(t\) 的最短路徑的連續的一段,可以反向。
考慮列舉免費路徑的開頭 \(x\), 計算出從 \(f_x, g_x\) 表示免費路徑的起點從 \(x\) 開始,\(x\) 到 \(v, u\) 的最短距離。
\[f_x = min (dv_x, f_y), g_x = min(du_x, g_y)\]然後答案就是 \(min(f_x + du_x, g_x + dv_x)\) 與 \(du_v\) 的最小值。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i = (a); i <= (b); i++) #define per(i, a, b) for (int i = (a); i >= (b); i--) #define fi first #define se second const int N = 4e5 + 10, inf = 0x3f3f3f3f, mod = 1e9 + 7; typedef pair <int, int> P; typedef long long LL; int n, m, s, t, cnt = 1, h[N], x, y; bool vis[N]; struct Edge { int to, next, w; } e[N]; struct Heap { LL v; int num; bool operator < (const Heap &mpc) const { return v > mpc.v; } }; LL ds_[N], dt_[N], dx_[N], dy_[N], ans = 1e16, f[N], g[N]; void add_(int u, int v, int w) { e[++cnt] = (Edge) {v, h[u], w}; h[u] = cnt; } void dijkstra_(int s, LL *d) { priority_queue <Heap> q; rep (i, 1, n) d[i] = 1e16; q.push((Heap) {0, s}), d[s] = 0; while (!q.empty()) { Heap cur = q.top(); q.pop(); int u = cur.num; if (cur.v != d[u]) continue; for (int v, i = h[u]; i; i = e[i].next) { v = e[i].to; if (d[v] > d[u] + e[i].w) { d[v] = d[u] + e[i].w; q.push((Heap) {d[v], v}); } } } } void dfs_(int u) { if (vis[u]) return; vis[u] = 1, f[u] = dy_[u], g[u] = dx_[u]; for (int v, i = h[u]; i; i = e[i].next) { v = e[i].to; if (ds_[u] + dt_[v] + e[i].w != ds_[t]) continue; dfs_(v); f[u] = min(f[u], f[v]), g[u] = min(g[u], g[v]); } ans = min(ans, min(f[u] + dx_[u], g[u] + dy_[u])); } int main() { scanf("%d%d%d%d%d%d", &n, &m, &s, &t, &x, &y); for (int u, v, w, i = 1; i <= m; i++) { scanf("%d%d%d", &u, &v, &w); add_(u, v, w), add_(v, u, w); } dijkstra_(s, ds_); dijkstra_(t, dt_); dijkstra_(x, dx_); dijkstra_(y, dy_); dfs_(s); printf("%lld\n", min(ans, dx_[y])); return 0; }