• [luogu2680]运输计划


    首先二分枚举答案t,考虑删去的边应满足的条件——所有大于t的链全部经过且长度不小于最长链-t,第二个条件很好判断,考虑第一个条件。

    先考虑有祖先-后代关系的链,用如果把这条链到1看成一个序列,那么差分一下再dfs一遍就可以对这条链上每一个点打上标记。

    然后没有祖先-后代关系的链,同样可以分解成两条链,到xlca(x,y)ylca(x,y),同样处理即可,最后时间复杂度o(nlogn)lca预处理)。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 300005
     4 struct ji{
     5     int nex,to,len;
     6 }edge[N<<1];
     7 int E,n,m,x,y,z,a[N],b[N],c[N],head[N],f[N][21],in[N],out[N],s[N],dp[N],ans[N];
     8 void add(int x,int y,int z){
     9     edge[E].nex=head[x];
    10     edge[E].to=y;
    11     edge[E].len=z;
    12     head[x]=E++;
    13 }
    14 bool pd(int x,int y){
    15     return (in[x]<=in[y])&&(out[y]<=out[x]);
    16 }
    17 int lca(int x,int y){
    18     if (pd(x,y))return x;
    19     for(int i=20;i>=0;i--)
    20         if (!pd(f[x][i],y))x=f[x][i];
    21     return f[x][0];
    22 }
    23 void dfs(int k,int fa,int sh){
    24     f[k][0]=fa;
    25     for(int i=1;i<=20;i++)f[k][i]=f[f[k][i-1]][i-1];
    26     s[k]=sh;
    27     in[k]=++x;
    28     for(int i=head[k];i!=-1;i=edge[i].nex)
    29         if (edge[i].to!=fa)dfs(edge[i].to,k,sh+edge[i].len);
    30     out[k]=++x;
    31 }
    32 void dfs2(int k,int fa){
    33     for(int i=head[k];i!=-1;i=edge[i].nex)
    34         if (edge[i].to!=fa){
    35             dfs2(edge[i].to,k);
    36             dp[k]+=dp[edge[i].to];
    37         }
    38 }
    39 bool pd(int k){
    40     int tot=0;
    41     memset(dp,0,sizeof(dp));
    42     for(int i=1;i<=m;i++)
    43         if (ans[i]>k){
    44             dp[a[i]]++;
    45             dp[b[i]]++;
    46             dp[c[i]]-=2;
    47             tot++;
    48         }
    49     dfs2(1,0);
    50     for(int i=1;i<=n;i++)
    51         if ((dp[i]==tot)&&(s[i]-s[f[i][0]]>=ans[0]-k))return 1;
    52     return 0;
    53 }
    54 int main(){
    55     scanf("%d%d",&n,&m);
    56     memset(head,-1,sizeof(head));
    57     for(int i=1;i<n;i++){
    58         scanf("%d%d%d",&x,&y,&z);
    59         add(x,y,z);
    60         add(y,x,z);
    61     }
    62     dfs(1,1,x=0);
    63     for(int i=1;i<=m;i++){
    64         scanf("%d%d",&a[i],&b[i]);
    65         c[i]=lca(a[i],b[i]);
    66         ans[i]=s[a[i]]+s[b[i]]-2*s[c[i]];
    67         ans[0]=max(ans[0],ans[i]);
    68     }
    69     x=0;
    70     y=ans[0];
    71     while (x<y){
    72         z=(x+y>>1);
    73         if (pd(z))y=z;
    74         else x=z+1;
    75     }
    76     printf("%d",x);
    77 }
    View Code
  • 相关阅读:
    邻接矩阵学习
    Spark on Yarn年度知识整理
    HBASE解析
    Storm的数据处理编程单元:Bolt 学习整理
    jsch ssh服务器调用Linux命令或脚本的小问题
    storm的数据源编程单元Spout学习整理
    Java 正则表达式详细使用
    【转】如何成为一个技术全面的架构师
    【转】Linux netstat命令详解,高级面试必备
    【转】Servlet 生命周期、工作原理
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11272087.html
Copyright © 2020-2023  润新知