NOIP2009 最优贸易

江枫思渺然 提交于 2019-12-04 07:07:44

题意

在一张节点带有权值的图上找出一条从 \(1\)\(n\) 的路径,使得路径上两点 \(p,q\) 满足先经过 \(p\) 再经过 \(q\) ,且 \(val[q]-val[p]\) 最大。

Luogu

分析

考虑跑两遍最短路,一遍求出经过每个节点时当前路径上的 \(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;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!