zoukankan      html  css  js  c++  java
  • B. 【普转提七联测 Day 6】载重

    题目大意

    B 国有 (n) 个城市, 一些城市间有若干条双向道路相连

    每条道路有一个限制重量,大于该限制重量的车都不能通过

    现在运输公司有 (q) 辆货车,每辆货车想从 (s_i) 市到 (t_i) 市,车的重量是 (w_i)

    请问每一辆车是否能够到达目的地

    Solution

    Std

    并查集在加边的时候从大到小加,并处理相关询问;

    由于从大到小加,可以保证当前是最优的方案,直接处理。

    实质也就是MST上的路径最值,不过离线下来,通过一个过程去实现,代码少。

    My Solution

    首先很明显求的是路径最小值最大。

    而显而易见,最大生成树可以保证树上最小值尽可能大。

    问题转换成求树上路径最小。

    最大生成树 + 路径最小值(树链剖分 + ST表)实现,或树上倍增。

    (mathrm{Code:})

    #include <algorithm>
    #include <climits>
    #include <cstdio>
    #include <iostream>
    #define rint register int
    #define FOR(i, a, b) for (rint i = (a); i <= (b); ++i)
    #define S_H(T, i, u) for (rint i = T.fl[u]; i; i = T.net[i])
    #define swap(x, y) (x ^= y ^= x ^= y)
    const int N = 1e5 + 10, M = 3e5 + 10;
    int n, m, Q;
    int si[N], hs[N], f[N], d[N], a[N];
    int top[N], tr[N], vs = 0, pr[N];
    class Edge {
       public:
        int x, y, z;
    } e[M << 1];
    struct Tree {
        int to[N << 1], net[N << 1], w[N << 1];
        int fl[N], len, in[N];
        inline void inc(int x, int y, int z) {
            to[++len] = y;
            w[len]    = z;
            ++in[y];
            net[len] = fl[x];
            fl[x]    = len;
        }
    } T;
    struct US_find {
        int f[N], n;
        inline void Build(int _) {
            n = _;
            FOR(i, 1, n)
            f[i] = i;
        }
        inline void Modify(int x, int y, int z) {
            int u = Get(x), v = Get(y);
            if (u != v) {
                f[u] = v;
                T.inc(x, y, z);
                T.inc(y, x, z);
            }
        }
        inline int Get(int x) { return x == f[x] ? x : f[x] = Get(f[x]); }
    };
    struct ST {
    #define I(k) (1 << k)
        int f[N][30], lg[N];
        inline int Ask(int l, int r) {
            int t = lg[r - l + 1];
            return std ::min(f[l][t], f[r - I(t) + 1][t]);
        }
        inline void Work() {
            lg[0] = -1;
            FOR(i, 1, n)
            lg[i] = lg[i >> 1] + 1;
            FOR(i, 1, n)
            f[i][0] = pr[i];
            FOR(j, 1, 20)
            FOR(i, 1, n - I(j) + 1)
            f[i][j] = std ::min(f[i][j - 1], f[i + I(j - 1)][j - 1]);
        }
    } S;
    											//定义部分
    inline int read() {
        int s = 0, w = 1;
        char c = getchar();
        while ((c < '0' || c > '9') && c != '-') c = getchar();
        if (c == '-') w = -1, c = getchar();
        while (c <= '9' && c >= '0')
            s = (s << 1) + (s << 3) + c - '0', c = getchar();
        return s * w;
    }
    template <class T>
    inline void write(T x) {
        if (x < 0) x = ~x + 1, putchar('-');
        if (x > 9) write(x / 10);
        putchar(x % 10 + 48);
        return void();
    }
    
    void dfs(int u, int fa) {
        si[u] = 1;
        S_H(T, i, u) {
            int v = T.to[i];
            if (v == fa) continue;
            f[v] = u, d[v] = d[u] + 1, a[v] = T.w[i];
            dfs(v, u);
            si[u] += si[v];
            hs[u] = si[hs[u]] < si[v] ? v : hs[u];
        }
    }
    void dfs_chain(int u, int k) {
        top[pr[tr[u] = ++vs] = u] = k, pr[vs] = a[u];
        if (!hs[u]) return void();
        dfs_chain(hs[u], k);
        S_H(T, i, u) {
            int v = T.to[i];
            if (v == f[u] || v == hs[u]) continue;
            dfs_chain(v, v);
        }
    }
    inline int Ask_chain(int x, int y) {
        int minn = INT_MAX;
        while (top[x] ^ top[y]) {
            if (d[top[x]] < d[top[y]]) swap(x, y);
            minn = std ::min(minn, S.Ask(tr[top[x]], tr[x]));
            x    = f[top[x]];
        }
        if (x == y) return minn;
        if (d[x] < d[y]) swap(x, y);
        minn = std ::min(minn, S.Ask(tr[y] + 1, tr[x]));
        return minn;
    }
     											//树链剖分操作
    inline bool cmp(Edge x, Edge y) { return x.z > y.z; }
    signed main(void) {
        n = read(), m = read(), Q = read();
        FOR(i, 1, m) {
            int x = read(), y = read(), z = read();
            e[i] = (Edge){x, y, z};
        }
        US_find F;
        F.Build(n);
        std ::sort(e + 1, e + m + 1, cmp);
        FOR(i, 1, m) F.Modify(e[i].x, e[i].y, e[i].z);
        //MST最大生成树
        FOR(i, 1, n)
        if (!si[i]) dfs(i, 0), dfs_chain(i, i);
        //树剖预处理
        S.Work();
        FOR(i, 1, Q) {
            int x = read(), y = read(), z = read();
            if (F.Get(x) != F.Get(y)) {
                puts("No");
                continue;
            }
            //特判是否连通 !important;
            int t = Ask_chain(x, y);
            t >= z ? puts("Yes") : puts("No");
        }
        return 0;
    }
    
  • 相关阅读:
    java核心技术卷上学习笔记
    个人作业——软件工程实践总结作业
    个人作业——软件产品案例分析
    软件工程作业-结对编程 2.0
    软件工程作业-结对编程 1.0
    软件工程作业2.0
    软件工程作业1.0
    《面向对象程序设计》c++第六次作业___calculator SE
    面向对象程序设计作业 6.1~6.4
    面向对象程序设计作业 5.1~5.5
  • 原文地址:https://www.cnblogs.com/yywxdgy/p/13220893.html
Copyright © 2011-2022 走看看