zoukankan      html  css  js  c++  java
  • [NOIp2015]运输计划

    Description

    BZOJ4326
    Luogu2680
    给定一棵树,和若干路径,求使一条边长度变为0后,最长路径的最小值。

    Solution

    链上的情况可以求出路径的交(差分或者运用前缀和的思想求“前缀交”),然后二分答案统计即可。
    推广到树上,首先可以树上差分,然后二分答案统计,也可以尝试树上路径求“前缀交”。

    Code

    差分版:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    
    const int N = 3e5 + 10;
    const int M = 2*N + 10;
    
    int hd[N], to[M], nxt[M], w[M], cnt;
    int dep[N], fa[N], sz[N], son[N];
    int top[N], id[N], rnk[N], tot;
    int n, m, mxd, mxe, fck;
    int flag[N], dis[N];
    int px[N], py[N], plca[N], pd[N];
    
    void adde(int x, int y, int z) {
        cnt++;
        to[cnt] = y; nxt[cnt] = hd[x]; w[cnt] = z;
        hd[x] = cnt;
    }
    
    int dfs1(int x, int f) {
        fa[x] = f;
        dep[x] = dep[f] + 1;
        sz[x] = 1;
        for (int i = hd[x]; i; i = nxt[i]) if (to[i] != f) {
            dis[to[i]] = dis[x] + w[i];
            sz[x] += dfs1(to[i], x);
            if (sz[to[i]] > sz[son[x]])
                son[x] = to[i];
        }
        return sz[x];
    }
    
    void dfs2(int x, int f) {
        top[x] = f;
        id[x] = tot++;
        rnk[tot] = x;
        if (!son[x]) return;
        dfs2(son[x], f);
        for (int i = hd[x]; i; i = nxt[i]) if (to[i] != fa[x] && to[i] != son[x]) {
            dfs2(to[i], to[i]);
        }
    }
    
    int lca(int x, int y) {
        while (top[x] != top[y]) {
            if (dep[top[x]] > dep[top[y]]) x = fa[top[x]];
            else y = fa[top[y]];
        }
        return dep[x] > dep[y] ? y : x;
    }
    
    bool check(int x) {
        fck = 0; memset(flag, 0, sizeof flag);
        for (int i = 1; i <= m; ++i) if (pd[i] > x) {
            flag[px[i]]++;
            flag[py[i]]++;
            flag[plca[i]] -= 2;
            fck++;
        }
        for (int i = n; i; --i) {
            int &j = rnk[i];
            flag[fa[j]] += flag[j];
            if (flag[j] == fck) {
                int fe = dis[j] - dis[fa[j]];
            	if (mxd - fe <= x) return true;
            }
        }
        return false;
    }
    
    int main() {
        scanf("%d%d", &n, &m);
        for (int i = 1, x, y, z; i < n; ++i) {
            scanf("%d%d%d", &x, &y, &z);
            adde(x, y, z);
            adde(y, x, z);
            mxe = std::max(mxe, z);
        }
        dfs1(1, 0);
        dfs2(1, 1);
        for (int i = 1; i <= m; ++i) {
            scanf("%d%d", &px[i], &py[i]);
            plca[i] = lca(px[i], py[i]); 
            pd[i] = dis[px[i]] + dis[py[i]] - 2 * dis[plca[i]];
            mxd = std::max(mxd, pd[i]);
        }
        int L = mxd - mxe, R = mxd;
        while (L < R) {
            int mid = (L + R) >> 1;
            if (check(mid)) {
                R = mid;
            } else {
                L = mid+1;
            }
        }
        printf("%d
    ", L);
        return 0;
    }
    

    TODO: “前缀交”版本

  • 相关阅读:
    程序员转型架构师,推荐你读这几本书
    Dubbo服务发现源码解析
    高可用架构之限流降级
    为什么Kafka速度那么快
    从分布式一致性到共识机制(三)拜占庭问题
    从分布式一致性到共识机制(二)Raft算法
    三分钟看完京东区块链白皮书
    轻松理解零知识证明
    三大去中心化交易协议对比
    从分布式一致性到共识机制(一)Paxos算法
  • 原文地址:https://www.cnblogs.com/wyxwyx/p/noip201523.html
Copyright © 2011-2022 走看看