• 洛谷 P2680 运输计划(二分答案+树上差分)


    题目链接:https://www.luogu.com.cn/problem/P2680

    首先是最小值最大的问题,可以考虑二分答案。

     首先用LCA预处理出u,v两点之间的距离,并记录最大距离。然后二分最小距离,如果u,v两点之间的距离小于二分的x,那么无需管它,否则进行树上差分,并且cnt++。如果cnt==0,直接可行;否则,对差分数组进行前缀和求每条边经过的次数。记录经过cnt次的边的边权最大值,如果u、v两点间的最大值减去边权最大值仍大于二分的x,那么不行。

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=300005;
     7 struct node{
     8     int to,next,w;
     9 }edge[N<<1];
    10 struct Node{
    11     int u,v,lca,sum;
    12 }q[N];
    13 int head[N],tot,cnt,maxx,m,n,maxh;
    14 int dep[N],f[N][30],e[N],dis[N],sa[N];
    15 void init(){
    16     memset(head,-1,sizeof(head));
    17 }
    18 void add(int u,int v,int w){
    19     edge[tot].next=head[u];
    20     edge[tot].to=v;
    21     edge[tot].w=w;
    22     head[u]=tot++;
    23 }
    24 void DFS(int u,int fa){
    25     dep[u]=dep[fa]+1;
    26     f[u][0]=fa;
    27     for(int i=1;(1<<i)<=dep[u];i++) f[u][i]=f[f[u][i-1]][i-1];
    28     for(int i=head[u];i!=-1;i=edge[i].next){
    29         int v=edge[i].to;
    30         if(v==fa) continue;
    31         dis[v]=dis[u]+edge[i].w;
    32         e[v]=edge[i].w;
    33         DFS(v,u);
    34     }
    35 }
    36 int lca(int u,int v){
    37     if(dep[u]<dep[v]) swap(u,v);
    38     for(int i=20;i>=0;i--) if(dep[f[u][i]]>=dep[v]) u=f[u][i];
    39     if(u==v) return u;
    40     for(int i=20;i>=0;i--) if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
    41     return f[u][0];
    42 }
    43 void get_sum(int u,int fa){
    44     for(int i=head[u];i!=-1;i=edge[i].next){
    45         int v=edge[i].to;
    46         if(v==fa) continue;
    47         get_sum(v,u);
    48         sa[u]+=sa[v];
    49     }
    50     if(sa[u]==cnt) maxx=max(maxx,e[u]);
    51 }
    52 int judge(int x){
    53     memset(sa,0,sizeof(sa));
    54     cnt=0;
    55     maxx=0;
    56     for(int i=1;i<=m;i++){
    57         if(q[i].sum<=x) continue;
    58         sa[q[i].u]++; sa[q[i].v]++;
    59         sa[q[i].lca]-=2;
    60         cnt++;
    61     }
    62     get_sum(1,0);
    63     if(cnt==0) return 1;
    64     if(maxh-maxx>x) return 0;
    65     return 1;
    66 }
    67 int main(){
    68     init();
    69     scanf("%d%d",&n,&m);
    70     for(int i=1;i<n;i++){
    71         int u,v,w;
    72         scanf("%d%d%d",&u,&v,&w);
    73         add(u,v,w); add(v,u,w);
    74     }
    75     DFS(1,0);
    76     for(int i=1;i<=m;i++){
    77         int u,v;
    78         scanf("%d%d",&u,&v);
    79         q[i].lca=lca(u,v);
    80         q[i].u=u; q[i].v=v;
    81         q[i].sum=dis[u]+dis[v]-2*dis[q[i].lca];
    82         maxh=max(maxh,q[i].sum);
    83     }
    84     int l=0,r=maxh,ans=0;
    85     while(l<=r){
    86         int mid=(l+r)>>1;
    87         if(judge(mid)) ans=mid,r=mid-1;
    88         else l=mid+1;
    89     }
    90     printf("%d
    ",ans);
    91     return 0;
    92 }
    AC代码
  • 相关阅读:
    Unbutu之web环境部署——常用软件安装
    利用百度uaredirect.js判断手机终端并自动跳转
    原生Ajax附件上传简单实例
    shader glsl 函数图举例
    pixijs释放纹理的方法
    pixijs shader透明度设置方法
    pixijs 用canvas的方法
    threejs 解决模型缩小有黑边的解决方案
    threejs 透明模型遮挡后面模型解决方案
    javascript canvas 清除图片空白多余的方法
  • 原文地址:https://www.cnblogs.com/New-ljx/p/13463722.html
Copyright © 2020-2023  润新知