zoukankan      html  css  js  c++  java
  • luogu2680 [NOIp2015]运输计划 (tarjanLca+二分答案+树上差分)

    我们先不会就二分一下答案,设它是x,我们要判断它能不能满足

    为了满足这个答案,我们就要让原本路径长度大于x的所有路径都经过某条边,而且这条边还要大于等于最长的路径-x

    于是运用树上差分的思想,对于所有长度>x的路径,给他的两端点处++,lca处--,这样统计树上每个点的子树的和,就是这个点与它父节点连边被经过的次数

    拿被经过次数>=长度大于x的路径条数的边 取一取最大值 然后判一判就行了

     1 #include<bits/stdc++.h>
     2 #define pa pair<int,int>
     3 #define CLR(a,x) memset(a,x,sizeof(a))
     4 using namespace std;
     5 typedef long long ll;
     6 const int maxn=3e5+10;
     7 
     8 inline ll rd(){
     9     ll x=0;char c=getchar();int neg=1;
    10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    12     return x*neg;
    13 }
    14 
    15 struct Edge{
    16     int b,l,ne;
    17 }eg[maxn*2],que[maxn*2];
    18 int N,M;
    19 int egh[maxn],ect,qh[maxn],lca[maxn],bfa[maxn];
    20 int dis[maxn],sum[maxn],ml,len[maxn];
    21 bool flag[maxn];
    22 
    23 inline void adeg(int a,int b,int l){
    24     eg[++ect].b=b;eg[ect].l=l;eg[ect].ne=egh[a];egh[a]=ect;
    25 }
    26 inline int getf(int x){return x==bfa[x]?x:bfa[x]=getf(bfa[x]);}
    27 
    28 void tarjan(int x){
    29     flag[x]=1;
    30     for(int i=egh[x];i;i=eg[i].ne){
    31         int b=eg[i].b;if(flag[b]) continue;
    32         dis[b]=dis[x]+eg[i].l;tarjan(b);
    33         bfa[getf(b)]=getf(x);
    34     }
    35     for(int i=qh[x];i;i=que[i].ne){
    36         int b=que[i].b;if(!flag[b]) continue;
    37         lca[i>>1]=getf(b);
    38     }
    39 }
    40 
    41 void dfs(int x,int f,int n){
    42     for(int i=egh[x];i;i=eg[i].ne){
    43         int b=eg[i].b;if(b==f) continue;
    44         dfs(b,x,n);sum[x]+=sum[b];
    45     }
    46     if(sum[x]>=n) ml=max(ml,dis[x]-dis[f]);
    47 }
    48 
    49 inline bool judge(int m){
    50     int c=0,mm=0;
    51     memset(sum,0,sizeof(sum));
    52     for(int i=1;i<=M;i++){
    53         if(len[i]>m){
    54             c++,mm=max(mm,len[i]);
    55             sum[que[i<<1].b]++;sum[que[i<<1|1].b]++;
    56             sum[lca[i]]-=2;
    57         }
    58     }
    59     ml=0;dfs(1,0,c);
    60     return mm-ml<=m;
    61 }
    62 
    63 int main(){
    64     //freopen(".in","r",stdin);
    65     int i,j,k;
    66     N=rd(),M=rd();
    67     for(i=1;i<N;i++){
    68         int a=rd(),b=rd(),c=rd();
    69         adeg(a,b,c);adeg(b,a,c);
    70     }
    71     for(i=1;i<=M;i++){
    72         int a=rd(),b=rd();
    73         que[i<<1].b=b;que[i<<1].ne=qh[a];qh[a]=i<<1;
    74         que[i<<1|1].b=a;que[i<<1|1].ne=qh[b];qh[b]=i<<1|1;
    75     }
    76     for(i=1;i<=N;i++) bfa[i]=i;
    77     tarjan(1);
    78     int mil=3e8,mal=0;
    79     for(i=1;i<=M;i++){
    80         len[i]=dis[que[i<<1].b]+dis[que[i<<1|1].b]-2*dis[lca[i]];
    81         mil=min(mil,len[i]);mal=max(mal,len[i]);
    82     }
    83     int l=max(mil-1000,0),r=mal,ans;
    84     while(l<=r){
    85         int m=l+r>>1;
    86         if(judge(m)) ans=m,r=m-1;
    87         else l=m+1;
    88     }
    89     printf("%d
    ",ans);
    90     return 0;
    91 }
  • 相关阅读:
    03 Java 修饰符
    04_Java 循环结构 for, while 及 do...while
    01_Java第一个程序_报错记录
    07_Java StringBuffer 和 StringBuilder 类_(修改,并且不产生新的未使用对象)
    06_Math 的 floor,round 和 ceil 方法实例比较_格式化字符串_String类
    [爱偷懒的程序员系列]Section 1. “懒”是一切需求的根源
    (1)Micropython+ESP32 点亮一个LED
    数据迁移测试方法【转】
    回来了回来了,失踪人口回归
    [爱偷懒的程序员系列]Section 4. 自定义钉钉消息推送
  • 原文地址:https://www.cnblogs.com/Ressed/p/9703662.html
Copyright © 2011-2022 走看看