【最短路】洛谷_1073 最优贸易

题意

给出一个图,求出从点 1 1 1到点 N N N的一条路径中选两个点 ( p , q ) (p,q) (p,q)使得 q − p q-p qp最大,其中要先经过 p p p再到 q q q

思路

求出 d d d f f f,其中 d i d_i di代表从点 1 1 1到点 i i i,能经过的权值最小的点的权值, f i f_i fi代表从点 i i i到点 N N N,能经过的权值最大的点的权值。
可以用 d i j k s t r a dijkstra dijkstra最短路的方法跑,只是要在最短路中把边权更新换成点权更新,至于 f f f,可以建个反图从 N N N跑。
最后枚举 i i i,使得 f i − d i f_i-d_i fidi最大

代码

#include
#include
#include
using namespace std;

int N, M, tot, ans;
int f[100001], d[100001], v[100001], head[3][100001], vis[100001];
struct node{
    int to, next;
}e[500001], ef[500001];

void add(int x, int y) {
    e[++tot].to = y;
    e[tot].next = head[1][x];
    head[1][x] = tot;
    ef[tot].to = x;
    ef[tot].next = head[2][y];
    head[2][y] = tot;
}

void calc_d() {
    memset(d, 127 / 3, sizeof(d));
    d[1] = v[1];
    priority_queue< pair<int, int> > q;
    q.push(make_pair(-v[1], 1));
    while (q.size()) {
        int x = q.top().second;
        q.pop();
        if (vis[x]) continue;
        vis[x] = 1;
        for (int i = head[1][x]; i; i = e[i].next) {
            int y = e[i].to;
            if (d[y] > min(d[x], v[y])) {//最小
                d[y] = min(d[x], v[y]);
                q.push(make_pair(-d[y], y));
            }
        }
    }
}

void calc_f() {
    memset(f, -127 / 3, sizeof(f));
    memset(vis, 0, sizeof(vis));
    f[N] = v[N];
    priority_queue< pair<int, int> > q;
    q.push(make_pair(-v[N], N));
    while (q.size()) {
        int x = q.top().second;
        q.pop();
        if (vis[x]) continue;
        vis[x] = 1;
        for (int i = head[2][x]; i; i = ef[i].next) {
            int y = ef[i].to;
            if (f[y] < max(f[x], v[y])) {//最大
                f[y] = max(f[x], v[y]);
                q.push(make_pair(-f[y], y));
            }
        }
    }
}

int main() {
    scanf("%d %d", &N, &M);
    for (int i = 1; i <= N; i++)
        scanf("%d", &v[i]);
    for (int i = 1, x, y, z; i <= M; i++) {
        scanf("%d %d %d", &x, &y, &z);
        add(x, y);
        if (z == 2) add(y, x);
    }
    calc_d();
    calc_f();
    for (int i = 1; i <= N; i++)
        ans = max(ans, f[i] - d[i]);
    printf("%d", ans);
}

你可能感兴趣的:(NOIP,图论)