坎坷经历(看题解的可略过)
- 其实这道题还是有点意思的,,,
- 其实看到这道题我脑子里想的一直是Tarjan缩点然后DAGdp,也不知道能不能做
- 看了眼题解好吧,,两遍SPFA,都是套路,,,
- 正经八本地打完SPFA发现不对劲,如果按照常规的SPFA开始加入的节点只有1号点,再加入其它节点时会发生问题,,
- 正经八本地把所有点都加进去,发现有些点其实是访问不到的,不能用它们更新答案
- 最后改对了。。
正经的题解
- 记minn和maxx数组,保存从1开始到x的最小值以及从n开始到x的最大值
- 把minn数组初始化为INF,maxx初始化为0
- 从1开始SPFA,把所有能更新的和值为INF的进行更新,注意,先考虑更新INF,在考虑松弛操作
- 从n开始反向SPFA
- 注意一下建边的时候要建正向边和反向边
- 枚举一遍1到n,根据
(maxx[i]−minn[i])
更新ans,输出ans即为结果
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxm = 2000000 + 50000;
const int maxn = 150000;
int minn[maxn], maxx[maxn];
int last[maxn], pre[maxm], other[maxm], len[maxm];
int tot = 0;
int n, m;
int x, y, z;
int que[maxn], vis[maxn];
int a[maxn];
void add(int x, int y, int z) {
tot++;
pre[tot] = last[x];
last[x] = tot;
other[tot] = y;
len[tot] = z;
}
void spfa1(void) {
que[1] = 1;
minn[1] = a[1];
int queh = 0, quet = 1;
while (queh != quet) {
queh = (queh + 1) % maxn;
int cur = que[queh];
vis[cur] = 0;
for (int p = last[cur]; p; p = pre[p]) {
if (len[p] == 2) continue;
int q = other[p];
if (minn[q] == 2139062143) {
minn[q] = a[q];
vis[q] = 1;
quet = (quet + 1) % maxn;
que[quet] = q;
}
if (minn[q] > minn[cur]) {
minn[q] = minn[cur];
if (!vis[q]) {
vis[q] = 1;
quet = (quet + 1) % maxn;
que[quet] = q;
}
}
}
}
}
void spfa2(void) {
que[1] = n;
maxx[n] = a[n];
int queh = 0, quet = 1;
while (queh != quet) {
queh = (queh + 1) % maxn;
int cur = que[queh];
vis[cur] = 0;
for (int p = last[cur]; p; p = pre[p]) {
if (len[p] == 1) continue;
int q = other[p];
if (maxx[q] == 0) {
maxx[q] = a[q];
quet = (quet + 1) % maxn;
vis[q] = 1;
que[quet] = q;
}
if (maxx[q] < maxx[cur]) {
maxx[q] = maxx[cur];
if (!vis[q]) {
vis[q] = 1;
quet = (quet + 1) % maxn;
que[quet] = q;
}
}
}
}
}
int main () {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= m; i++) {
scanf("%d %d %d", &x, &y, &z);
if (z == 2) {
add(x, y, 1);
add(y, x, 1);
add(x, y, 2);
add(y, x, 2);
} else {
add(x, y, 1);
add(y, x, 2);
}
}
memset(minn, 127, sizeof(minn));
memset(maxx, 0, sizeof(maxx));
spfa1();
spfa2();
int ans = 0;
for (int i = 1; i <= n; i++) {
ans = std :: max(ans, maxx[i] - minn[i]);
}
printf("%d", ans);
return 0;
}