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

    传送门

    要最长链的长度最短,一秒想到二分,因为如果对于某个长度满足改掉一边的边权后能使得所有链长度不超过该长度,则所有比他长的长度也满足.

    二分最终答案.我们要使得原来长度大于二分的(mid)的链删边后小于(mid),所以要找出一条最长的,被所有长度大于(mid)的链包含的边,使得最长链长度减去这条边长度不超过(mid)

    用树剖求出(lca),用来求每条链的长度.我们还要在check的时候知道每条边被哪些长度大于(mid)的链覆盖,使用差分即可

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define LL long long
    #define il inline
    #define re register
    #define db double
    #define max(a,b) ((a)>(b)?(a):(b))
    
    using namespace std;
    const int N=300000+10;
    il LL rd()
    {
        re LL x=0,w=1;re char ch=0;
        while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    int to[N<<2],nt[N<<2],w[N<<2],hd[N],tot=1;
    il void add(int x,int y,int z)
    {
      ++tot;to[tot]=y;nt[tot]=hd[x];w[tot]=z;hd[x]=tot;
      ++tot;to[tot]=x;nt[tot]=hd[y];w[tot]=z;hd[y]=tot;
    }
    int n,sz[N],de[N],hc[N],top[N],dis[N],fae[N],fa[N],a[N],m,q[N][3],len[N],maxl,ma,nm;
    il void dfs1(int x,int ffa)
    {
      sz[x]=1;
      for(re int i=hd[x];i;i=nt[i])
        {
          int y=to[i];
          if(y==ffa) continue;
          dis[y]=dis[x]+w[i],de[y]=de[x]+1,fae[y]=w[i],fa[y]=x;
          dfs1(y,x);
          sz[x]+=sz[y];
          if(sz[y]>sz[hc[x]]) hc[x]=y;
        }
    }
    il void dfs2(int x,int ffa)
    {
      if(hc[x])
        {
          top[hc[x]]=top[x];
          dfs2(hc[x],x);
        }
      for(re int i=hd[x];i;i=nt[i])
        {
          int y=to[i];
          if(y==ffa||y==hc[x]) continue;
          top[y]=y;
          dfs2(y,x);
        }
    }
    il void dd(int x,int ffa)
    {
      for(re int i=hd[x];i;i=nt[i])
        {
          int y=to[i];
          if(y==ffa) continue;
          dd(y,x);
          a[x]+=a[y];
          if(a[y]>=nm) ma=max(ma,fae[y]);
        }
    }
    il bool check(int mid)
    {
      ma=nm=0;
      for(re int i=1;i<=n;i++) a[i]=0;
      for(re int i=1;i<=m;i++)
        if(len[i]>mid) ++a[q[i][0]],++a[q[i][1]],----a[q[i][2]],++nm;
      dd(1,0);
      return mid>=maxl-ma;
    }
    
    int main()
    {
      n=rd(),m=rd();
      for(re int i=1;i<n;i++)
        {
          int x=rd(),y=rd(),z=rd();
          add(x,y,z);
        }
      de[1]=1,dfs1(1,0),top[1]=1,dfs2(1,0);
      for(re int i=1;i<=m;i++)
        {
          int x=q[i][0]=rd(),y=q[i][1]=rd();
          while(top[x]!=top[y])
        	{
        	  if(de[top[x]]<de[top[y]]) swap(x,y);
        	  len[i]+=dis[x]-dis[top[x]]+fae[top[x]];
        	  x=fa[top[x]];
        	}
          if(de[x]<de[y]) swap(x,y);
          len[i]+=dis[x]-dis[y];
          q[i][2]=y;
          maxl=max(maxl,len[i]);
        }
      int l=0,r=maxl,mid,ans=maxl;
      while(l<=r)
        {
          mid=(l+r)>>1;
          if(check(mid)) r=mid-1,ans=mid;
          else l=mid+1;
        }
      printf("%d
    ",ans);
      return 0;
    }
    
    
  • 相关阅读:
    基本运算符和if判断
    数据类型
    Day 5内存管理,定义变量
    Day 4 变量常量
    编辑语言的分类
    硬盘工作原理
    计算机组成原理
    hdu5293 lca+dp+树状数组+时间戳
    hdu5290树形dp
    hdu5294 网络流+dijskstr
  • 原文地址:https://www.cnblogs.com/smyjr/p/9608284.html
Copyright © 2011-2022 走看看