[Luogu] 货车运输

Posted xayata

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Luogu] 货车运输相关的知识,希望对你有一定的参考价值。

https://www.luogu.org/problemnew/show/1967

kruskal + Lca

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <string>

using namespace std;
const int N = 1e5 + 10;

#define oo 99999999

struct Node {
    int u, v, w;
} S[N * 5];
struct Edge {
    int u, v, w, nxt;
} E[N << 1];

int now = 1, n, m, js;
int head[N], p[N], f[N][25], g[N][25], deep[N];

inline int read() {
    int x = 0;
    char c = getchar();
    while(c < 0 || c > 9) c = getchar();
    while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = getchar();
    return x;
}

inline bool cmp(Node a, Node b) {
    return a.w > b.w;
}

int getf(int x) {
    return p[x] == x ? x : p[x] = getf(p[x]);
}

void add(int u, int v, int w) {
    E[now].v = v;
    E[now].w = w;
    E[now].nxt = head[u];
    head[u] = now ++;
}

inline void Kruskal() {
    for(int i = 1, doen = 1; i <= (m << 1) && doen < n; i ++) {
        int u = S[i].u, v = S[i].v;
        int pu = getf(u), pv = getf(v);
        if(pu != pv) {
            p[pu] = pv;
            add(u, v, S[i].w);
            add(v, u, S[i].w);
            doen ++;
        }
    }
}

void make_deep(int u, int depth) {
    deep[u] = depth;
    for(int i = head[u]; ~ i; i = E[i].nxt) {
        int v = E[i].v;
        if(!deep[v]) {
            f[v][0] = u;
            g[v][0] = E[i].w;
            make_deep(v, depth + 1);
        }
    }
}

inline void make_jump() {
    for(int j = 1; (1 << j) <= n; j ++)
        for(int i = 1; i <= n; i ++)
            if(f[i][j - 1]) f[i][j] = f[f[i][j - 1]][j - 1], g[i][j] = min(g[i][j - 1], g[f[i][j - 1]][j - 1]);
}

inline int lca(int x, int y) {
    int ret = oo;
    if(x == y) return 0;
    if(deep[x] < deep[y]) swap(x, y);
    int k = log2(deep[x]);
    for(int i = k; i >= 0; i --) {
        if(deep[f[x][i]] >= deep[y]) {
            ret = min(ret, g[x][i]);
            x = f[x][i];
        }
    }
    if(x == y) return ret;
    for(int i = k; i >= 0; i --) {
        if(f[x][i] != f[y][i]) {
            ret = min(ret, min(g[x][i], g[y][i]));
            x = f[x][i];
            y = f[y][i];
        }
    }
    ret = min(ret, min(g[x][0], g[y][0]));
    return ret;
}

int main() {
    n = read();
    m = read();
    for(int i = 1; i <= n; i ++) head[i] = -1, p[i] = i;
    for(int i = 1; i <= m; i ++) S[i].u = read(), S[i].v = read(), S[i].w = read();
    sort(S + 1, S + m + 1, cmp);
    Kruskal();
    for(int i = 1; i <= n; i ++)
        if(!deep[i])
            make_deep(i, 1);//可能会有多块
    make_jump();
    int T = read();
    while(T --) {
        int x = read(), y = read();
        if(getf(x) != getf(y)) {
            printf("-1\n");
            continue ;
        }
        int answer = lca(x, y);
        printf("%d\n", answer);
    }
    return 0;
}

 

以上是关于[Luogu] 货车运输的主要内容,如果未能解决你的问题,请参考以下文章

luogu P1967 货车运输

[luogu 1967]货车运输

Luogu-P1967 货车运输

Luogu P1967 货车运输

Luogu P1967 货车运输题解

luogu P1967 货车运输 最大生成树 倍增LCA