题意
在一张节点带有权值的图上找出一条从 \(1\) 到 \(n\) 的路径,使得路径上两点 \(p,q\) 满足先经过 \(p\) 再经过 \(q\) ,且 \(val[q]-val[p]\) 最大。
分析
考虑跑两遍最短路,一遍求出经过每个节点时当前路径上的 \(val_{min}\) ,另一遍反向求出 \(val_{max}\) 。
于是就可以再建一个反图,两次SPFA,最后枚举每个节点找出 \(max(d[2][i]-d[1][i])\)就完事辣。
但似乎有神仙只有32行代码......
代码
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 100003 #define M 500003 #define il inline #define re register #define INF 0x3f3f3f3f #define tie0 cin.tie(0),cout.tie(0) #define fastio ios::sync_with_stdio(false) #define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout) using namespace std; typedef long long ll; template <typename T> inline void read(T &x) { T f = 1; x = 0; char c; for (c = getchar(); !isdigit(c); c = getchar()) if (c == '-') f = -1; for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48); x *= f; } struct edge { int to, nxt; } e1[M], e2[M]; int n, m, ans; int val[N], d[3][N]; int h1[M], h2[M], c1, c2; bool vis[N]; void insert(int u, int v) { e1[++c1].to = v, e1[c1].nxt = h1[u], h1[u] = c1; e2[++c2].to = u, e2[c2].nxt = h2[v], h2[v] = c2; } void SPFA(int s, int t) { memset(vis, 0, sizeof vis); queue <int> q; if (s == 1) { for (int i = 1; i <= n; ++i) d[1][i] = INF; d[1][s] = val[s]; q.push(s); vis[s] = 1; while (!q.empty()) { int u = q.front(); q.pop(); vis[u] = 0; for (int i = h1[u]; i; i = e1[i].nxt) { int v = e1[i].to; if (d[1][v] > min(d[1][u], val[v])) { d[1][v] = min(d[1][u], val[v]); if (!vis[v]) q.push(v), vis[v] = 1; } } } } else { for (int i = 1; i <= n; ++i) d[2][i] = 0; d[2][s] = val[s]; q.push(s); vis[s] = 1; while (!q.empty()) { int u = q.front(); q.pop(); vis[u] = 0; for (int i = h2[u]; i; i = e2[i].nxt) { int v = e2[i].to; if (d[2][v] < max(d[2][u], val[v])) { d[2][v] = max(d[2][u], val[v]); if (!vis[v]) q.push(v), vis[v] = 1; } } } } } int main() { int x, y, z; read(n), read(m); for (int i = 1; i <= n; ++i) read(val[i]); for (int i = 1; i <= m; ++i) { read(x), read(y), read(z); if (z == 1) insert(x, y); else insert(x, y), insert(y, x); } SPFA(1, n), SPFA(n, 1); for (int i = 1; i <= n; ++i) ans = max(ans, d[2][i] - d[1][i]); printf("%d", ans); return 0; }