• [NOIP2015] 运输计划


    [NOIP2015]运输计划

    "守得云开见月明"

    题目大意:给出一颗树,若干个起点和终点,可以消去一条边的边权,要求起点到终点的最短路径中最长的一条能有多短.

    本来想树剖??维护最大值和链长,然后并不懂怎么二分.看了看发现可以用(lca)啊蠢猪(做的题太少了),尝试了树剖(lca),好写还快.

    而二分的策略是这样的,你要删去的边肯定是当前最大路径中的一条边,虽然我们不知道这条路径包含最大的边是多少,但是取当前树中的最长边已经足够把初始的左右边界缩小很多了.然后我们取(mid),进行(check),那(check​)的规则是这样的:

    • 取每一条路径的长度,和(mid)比较,如果小于,则忽略,因为完全不用改变,如果大于,则需要进行一点标记,将(s)(t)(lca)的标记(-2),(s)(t)标记分别(+1),然后(tot+1)

    • 按照(dfs)序倒序遍历,保证父亲先继承所有儿子结点的标记数,然后要判断父边和当前的二分出的长度的关系,以及点的标记数是否等于(tot),两者都满足,则返回(true),否则继续循环,循环结束,返回(false).

      为什么这样的策略正确呢?因为首先你只能消去一条边的权值,也就是比当前二分出的答案还要大的路径中都要消去同一条包含的边,且消去后满足这些边都可以比当前最大值最小小.

      因为是在树上,我们完全可以用点来表示边.树上差分来判断这条边是否都被包含.也就是父亲继承儿子的标记,

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    
    using std::max;
    
    const int N = 300007;
    
    struct Edge{
        int to, val, next;
    }e[N << 1];
    
    int n, m, cnt, dfs_clock, e_max, d_max, ans;
    int q[N], f[N], head[N], fa[N], top[N], deep[N], son[N], size[N], val[N], anc[N], s[N], t[N];
    int cost[N], dis[N];
    
    inline void addedge(int x, int y, int z){
        ++cnt;
        e[cnt].to = y;
        e[cnt].val = z;
        e[cnt].next = head[x];
        head[x] = cnt;
    }
    
    inline int read() {//读入优化
        int re = 0;
        char ch = getchar();
        while (ch <'0' || ch > '9') ch = getchar();
        while (ch >= '0' && ch <= '9'){ 
            re = re * 10 + ch - '0'; 
            ch = getchar();
        }
        return re;
    }
    
    void dfs_1(int u, int father, int depth){
        size[u] = 1, son[u] = 0, fa[u] = father, deep[u] = depth;
        for(int i = head[u], v; i; i = e[i].next){
            v = e[i].to;
            if(v == father) continue;
            
            val[v] = val[u] + e[i].val;
            dfs_1(v, u, depth + 1);
            cost[v] = e[i].val;
    
            size[u] += size[v];
            if(size[v] > size[son[u]]){
                son[u] = v;
            }
        }
        return;
    }
    
    void dfs_2(int u, int tp){
        q[++dfs_clock] = u, top[u] = tp;
        if(son[u]) dfs_2(son[u], tp);
        for(int i = head[u], v; i; i = e[i].next){
            v = e[i].to;
            if(v == fa[u] || v == son[u]) continue;
            dfs_2(v, v);
        }
        return;
    }
    
    inline int lca(int x, int y){
        while(top[x] != top[y]){
            if(deep[top[x]] >= deep[top[y]]) x = fa[top[x]];
            else y = fa[top[y]];
        }
        if(deep[x] < deep[y]) return x; return y;
    }
    
    inline bool check(int fff){
        memset(f, 0, sizeof(f));
        int tot = 0;
        for(int i = 1; i <= m; ++i){
            if(dis[i] > fff){
                f[s[i]]++, f[t[i]]++, f[anc[i]] -= 2, tot++;
            }
                
        }
        for(int i = n; i; --i){
            f[fa[q[i]]] += f[q[i]];
            
            if(cost[q[i]] >= d_max - fff &&  f[q[i]] == tot){
                return true;
            }
        }
        return false;
    }
    
    int main(){
        n = read(), m = read();
        int la, lb, lc;
        for(int i = 1; i <= n - 1; ++i){
            la = read(), lb = read(), lc = read();
            addedge(la, lb, lc);
            addedge(lb, la, lc);
            e_max = max(e_max, lc);
        }
        dfs_1(1, 0, 0);
     	dfs_2(1, 1);
        for(int i = 1; i <= m; ++i){
            s[i] = read(), t[i] = read();
     		anc[i] = lca(s[i], t[i]);
            dis[i] = val[s[i]] + val[t[i]] - val[anc[i]] * 2;
            d_max = max(d_max, dis[i]);
        }
        int l = d_max - e_max, r = d_max, mid;
        while(l <= r){
            mid = l + ((r - l) >> 1);
            if(check(mid)){
                r = mid - 1;
                ans = mid;
            } 
            else l = mid + 1;
        }
        printf("%d
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    asp.net区
    推荐大家一个保护视力的Visual Studio皮肤
    微软Team Foundation Server相关技术
    TFS2008安装图解(详细版本)
    VS2008 ,TFS2008破解序列号
    分析器错误信息: 发现不明确的匹配。
    ASP.NET MVC Routing概述
    软件工程文档编写
    Visual SourceSafe学习小结
    aspnetpager 详解 (转)
  • 原文地址:https://www.cnblogs.com/LMSH7/p/9509340.html
Copyright © 2020-2023  润新知