NOIP2009 最优贸易
题意
在一张节点带有权值的图上找出一条从 \(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;
}

浙公网安备 33010602011771号