• [NOIP2015 提高组] 运输计划


    [NOIP2015 提高组] 运输计划

    0x01 题意

    给定一棵树,边有权值,给定树上的若干条路径,求把一条边的权值变为0后,这些路径中的最长路径长是多少

    0x02 解

    答案具有单调性,所以可以二分路径长找答案

    我们发现把其中一条边权变为0,这条边一定在最长路径上,如果不在最长路径上,那么答案不是最优的

    所以我们check函数中,判断有没有一条边,边权为w,满足(二分路径长>=最长路径-w)即可

    但是考虑到删掉一条边后有可能其他路径长会大于之前的最长路径成为新的最长路径

    在二分时我们把大于二分路径长的路径在树上差分计数,当我们枚举到的那条边在所有大于二分路径长的路径上时,这些路径会同时减掉这条边的边权,这样就避免了其他路径成为最长路径

    0x03 码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<queue>
    #include<deque>
    #include<set>
    #include<stack>
    #include<bitset>
    #include<cstring>
    #define ll long long
    using namespace std;
    const int INF=0x3f3f3f3f,N=300010;
    
    inline int read(){
        int x=0,y=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') y=-1;c=getchar();}
        while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x*y;
    }
    
    int e[4*N],ne[4*N],w[4*N],h[N],idx;
    int f[N],d[N],siz[N],ms[N],top[N],id[N],rk[N],cnt=0,sum=0,val[N],dis[N];
    int n,m;
    int qa[N],qb[N],qlca[N],qd[N],maxd,maxl;
    int buc[N];
    
    void add(int a,int b,int c){
        e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
    }
    
    void dfs1(int x,int fa){
        f[x]=fa;
        d[x]=d[fa]+1;
        siz[x]=1;
        for(int i=h[x];~i;i=ne[i]){
            int j=e[i];
            if(j==fa) continue;
            dis[j]=dis[x]+w[i];
            val[j]=w[i];
            dfs1(j,x);
            siz[x]+=siz[j];
            if(!ms[x]||siz[ms[x]]<siz[j]) ms[x]=j;
        }
    }
    
    void dfs2(int x,int topp){
        top[x]=topp;id[x]=++cnt,rk[cnt]=x;
        if(!ms[x]) return;
        dfs2(ms[x],topp);
        for(int i=h[x];~i;i=ne[i]){
            int j=e[i];
            if(j==f[x]||j==ms[x]) continue;
            dfs2(j,j);
        }
    }
    
    int lca(int a,int b){
        while(top[a]!=top[b]){
            if(d[top[a]]<d[top[b]]) swap(a,b);
            a=f[top[a]];
        }
        return d[a]<=d[b]?a:b;
    }
    
    bool check(int x){
        memset(buc,0,sizeof buc);
        sum=0;
        for(int i=1;i<=m;i++){
            if(qd[i]>x){
                buc[qa[i]]++;
                buc[qb[i]]++;
                buc[qlca[i]]-=2;
                sum++;
            }
        }
        for(int i=n;i>=1;i--){
            buc[f[rk[i]]]+=buc[rk[i]];
            if(val[rk[i]]>=maxd-x&&buc[rk[i]]==sum){
                return 1;
            }
        }
        return 0;
    }
    
    int biss(int a,int b){
        int l=a,r=b;
        while(l<r){
            int mid=(l+r)>>1;
            if(check(mid)) r=mid;
            else l=mid+1;
        }
        return l;
    }
    
    int main(){
    
        memset(h,-1,sizeof h);
        
        n=read();
        m=read();
        for(int i=1;i<n;i++){
            int a,b,t;
            a=read(),b=read(),t=read();
            add(a,b,t);
            add(b,a,t);
            maxl=max(maxl,t);
        }
        dfs1(1,0),dfs2(1,1);
        for(int i=1;i<=m;i++){
            qa[i]=read(),qb[i]=read();
            qlca[i]=lca(qa[i],qb[i]);
            qd[i]=dis[qa[i]]+dis[qb[i]]-2*dis[qlca[i]];
            maxd=max(maxd,qd[i]);
        }
    
        int ans=biss(maxd-maxl,maxd+1);
    
        cout<<ans;
    
        return 0;
    }
    
  • 相关阅读:
    mybatis+spring报错PropertyAccessException 1: org.springframework.beans.MethodInvocationException
    jQuery实现判断li的个数从而实现其他功能
    移动平台对 meta 标签的定义
    移动平台对 meta 标签的定义
    HTML5手机网站开发页面宽度解决方案
    HTML5手机网站开发页面宽度解决方案
    别做“不会思考的码农”
    别做“不会思考的码农”
    myeclipse+spket1.6+Extjs4.2开发环境搭建
    myeclipse+spket1.6+Extjs4.2开发环境搭建
  • 原文地址:https://www.cnblogs.com/wsyunine/p/14959942.html
Copyright © 2020-2023  润新知