• [luogu P1967] 货车运输


    题目链接:

    货车运输

    题目分析:

    kruscal+树剖板套板

    首先在一个连通块里的两个点之间的路径上边权最小值的最大值(有点绕)一定在最大生成树上,因为最大生成树使新图连通且边权最大
    然后在最大生成树上树剖/倍增求两点路径中的最小值即可,注意边权下放到点后查询时要跳过(LCA)
    图可能不连通((#21)即是不连通的情况),此时需要对每棵(BST)的根(dfs)一遍

    代码:

    #include<bits/stdc++.h>
    #define N (100000 + 10)
    #define int long long
    using namespace std;
    inline int read() {
        int cnt = 0, f = 1; char c = getchar();
        while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
        while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + c - '0'; c = getchar();}
        return cnt * f;
    }
    const int INF = (1 << 30);
    int n, m;
    int fa[N], father[N], tot, w[N], a[N], num[N], id[N], idx, top[N], dep[N], siz[N], son[N];
    int nxt[N], first[N], to[N];
    int x, y, z, q;
    struct node {
        int u, v, dat;
    }edge[N];
    bool cmp (node x, node y) {
        return x.dat > y.dat;
    }
    void add(int x, int y, int z) {nxt[++tot] = first[x], first[x] = tot, to[tot] = y, w[tot] = z;}
    int get_father(int x) {return fa[x] == x ? x : fa[x] = get_father(fa[x]);}
    void dfs_(int x, int Fa) {
        father[x] = Fa, dep[x] = dep[Fa] + 1, siz[x] = 1;
        for (register int i = first[x]; i; i = nxt[i]) {
            int v = to[i];
            if (v == Fa) continue;
            a[v] = w[i];
            dfs_(v, x);
            siz[x] += siz[v];
            if (siz[son[x]] < siz[v]) son[x] = v;
        }
    }
    void dfs__(int x, int tp) {
        top[x] = tp, num[x] = ++idx, id[idx] = x;
        if (son[x]) dfs__(son[x], tp);
        for (register int i = first[x]; i; i = nxt[i]) {
            int v = to[i];
            if (num[v]) continue;
            dfs__(v, v);
        }
    }
    struct node2 {
        int l, r, dat;
        #define l(p) tree[p].l
        #define r(p) tree[p].r
        #define dat(p) tree[p].dat 
    }tree[N << 2];
    void pushup(int p) {
        dat(p) = min(dat(p << 1), dat(p << 1 | 1));
    }
    void build (int p, int l, int r) {
        l(p) = l, r(p) = r;
        if (l == r) {dat(p) = a[id[l]]; return;}
        int mid = (l + r) >> 1;
        build (p << 1, l, mid);
        build (p << 1 | 1, mid + 1, r);
        pushup(p);
    }
    long long query (int p, int l, int r) {
    	if (l <= l(p) && r >= r(p)) return dat(p);
    	long long ans = INF;
    	int mid = (l(p) + r(p)) >> 1;
    	if (l <= mid) ans = min(ans, query(p << 1, l, r));
    	if (r > mid) ans = min(ans, query(p << 1 | 1, l, r));
    	return ans;
    }
    long long Query(int u, int v) {
    	long long ans = INF;
        while (top[u] != top[v]) {
            if (dep[top[u]] < dep[top[v]]) swap(u, v);
    		ans = min(ans, query(1, num[top[u]], num[u]));
    		u = father[top[u]];
        }
        if (dep[u] < dep[v]) swap(u, v);
    	ans = min(ans, query(1, num[v] + 1, num[u]));
    	return ans; 
    }
    signed main() {
        n = read(), m = read();
        for (register int i = 1; i <= n; ++i) fa[i] = i;
        for (register int i = 1; i <= m; ++i) {
            edge[i].u = read(), edge[i].v = read(), edge[i].dat = read();
        }
        sort (edge + 1, edge + m + 1, cmp);
        for (register int i = 1; i <= m; i++) {
        	if (tot / 2 == n - 1) break;
            int fx = get_father(edge[i].u), fy = get_father(edge[i].v);
            if (fx == fy) continue;
            fa[fy] = fx, add(edge[i].u, edge[i].v, edge[i].dat), add(edge[i].v, edge[i].u, edge[i].dat);
        }
        for (register int i = 1; i <= n; ++i) if (fa[i] == i) dfs_(i, 0), dfs__(i, i);
        build(1, 1, n);
        q = read();
        for (register int i = 1; i <= q; ++i) {
            x = read(), y = read();
            if (get_father(x) != get_father(y)) {printf("-1
    "); continue;}
    		printf("%lld
    ", Query(x, y));
        }
        return 0;
    }
    
  • 相关阅读:
    Root of AVL Tree
    04-树4 是否同一棵二叉搜索树
    03-树3 Tree Traversals Again
    03-树2 List Leaves
    283. Move Zeroes
    506. Relative Ranks
    492. Construct the Rectangle
    476. Number Complement
    461. Hamming Distance
    389. Find the Difference
  • 原文地址:https://www.cnblogs.com/kma093/p/11539580.html
Copyright © 2020-2023  润新知