zoukankan      html  css  js  c++  java
  • Luogu P2680 运输计划

    题目链接:Click here

    Solution:

    我们要使最大值最小,显然二分

    二分一个最大值,小于等于最大值的路径就不用管了,看大于最大值的路径

    记录要使剩下的路径的最大值小于等于当前二分的值,要减去的最小边长maxd

    然后我们就是要查找是否有一条被剩下的所有路径都经过的,长度大于等于maxd边

    我们可以用树上差分来记录一条边被多少条路径经过

    对于一条路径,我们使(d[u]++)(d[v]++)(d[lca(u,v)]-2)(f[x])代表以(x)为根的子树(d)值之和

    对于任意(f[x]=tot),则说明(x)连向(fa[x])的这条边被所有路径都经过了

    用倍增求lca会T,所以我们用树剖来求lca(关于倍增,它死了>)

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=3e5+1;
    int n,m,cnt,head[N],dis[N],fdis[N];
    int maxn,f[N][32],dif[N],dep[N];
    int son[N],sz[N],fa[N],top[N];
    struct Edge{int nxt,to,val;}edge[N<<1];
    struct Road{int ds,u,v,lca;}p[N];
    void ins(int x,int y,int z){
        edge[++cnt].nxt=head[x];
        edge[cnt].to=y;head[x]=cnt;
        edge[cnt].val=z;
    }
    void dfs1(int x,int fat){
        for(int i=head[x];i;i=edge[i].nxt){
            int y=edge[i].to;
            if(y==fat) continue;
            fa[y]=x;dep[y]=dep[x]+1;
            dis[y]=dis[x]+edge[i].val;
            fdis[y]=edge[i].val;
            dfs1(y,x);sz[x]+=sz[y];
            if(sz[y]>sz[son[x]]) son[x]=y;
        }sz[x]++;
    }
    void dfs2(int x,int topx){
        top[x]=topx;
        if(!son[x]) return ;
        dfs2(son[x],topx);
        for(int i=head[x];i;i=edge[i].nxt){
            int y=edge[i].to;
            if(y==fa[x]||y==son[x]) continue;
            dfs2(y,y);
        }
    }
    int Lca(int x,int y){
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y]) swap(x,y);
        return x;
    }
    int dist(int x,int y){
        return dis[x]+dis[y]-(dis[Lca(x,y)]<<1);
    }
    void getdif(int x){
        for(int i=head[x];i;i=edge[i].nxt){
            int y=edge[i].to;
            if(y==fa[x]) continue;
            getdif(y);dif[x]+=dif[y];
        }    
    }
    int check(int mid){
        int tot=0,maxd=0;
        memset(dif,0,sizeof(dif));
        for(int i=1;i<=m;i++){
            if(p[i].ds<=mid) continue;
            dif[p[i].u]++,dif[p[i].v]++;
            dif[p[i].lca]-=2;++tot;
            maxd=max(maxd,p[i].ds-mid);
        }getdif(1);
        for(int i=2;i<=n;i++)
            if(maxd<=fdis[i]&&dif[i]>=tot) return 1;
        return 0;
    }
    int read(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
        return x*f;
    }
    signed main(){
        n=read(),m=read();
        for(int i=1;i<n;i++){
            int x=read(),y=read(),z=read();
            ins(x,y,z),ins(y,x,z);
        }dfs1(1,0);dfs2(1,1);
        for(int i=1;i<=m;i++){
            int x=read(),y=read();
            p[i].u=x,p[i].v=y;
            p[i].lca=Lca(x,y);
            p[i].ds=dist(x,y);
            maxn=max(maxn,p[i].ds);
        }
        int l=0,r=maxn,re=-1;
        while(l<=r){
            int mid=l+r>>1;
            if(check(mid)) re=mid,r=mid-1;
            else l=mid+1;
        }printf("%d
    ",re);
        return 0;
    }
    
  • 相关阅读:
    word设置的密码忘了怎么办?
    Navicat Report Viewer 设置 HTTP 的方法
    如何处理Navicat Report Viewer 报表
    excel密码忘记了怎么办
    Beyond Compare文本比较搜索功能详解
    Popular Cows POJ
    Problem B. Harvest of Apples HDU
    网络流模型整理
    The Shortest Statement CodeForces
    Vasya and Multisets CodeForces
  • 原文地址:https://www.cnblogs.com/NLDQY/p/11518644.html
Copyright © 2011-2022 走看看