• [NOIP2015]运输计划


    题意简述:给定一颗$N$个点边带权的树,再给定$M$条链,问将树上的某条边权值改为0后,这些链中最长的至少有多长。

    由于答案显然具有单调性,因此可以考虑二分答案。

    二分答案后就变成了这样一个问题:将一条边的边权变为0后,是否可以让所有m条路径中每条的权值都小于$mid$;

    这个问题乍一看还是没啥思路,不妨更加深入的分情况来看。

    对于权值和小于$mid$的链,怎么改他也是符合条件的,因此可以不考虑。

    对于权值和大于$mid$的链,由于只能修改一条边,因此我们必须找到一条边使得其为所有链长大于$mid$的指定链的公共部分。

    光是公共部分还不够,还需要有长度限制。设$m$条链中长度最长的为$mx$,则我们找到的边必须要大于等于$mx-mid$

    对于第二个问题十分好解决,直接看这条边的边权即可。

    对于第一个问题,我们使用树上差分的方式,将每条边被覆盖的次数进行统计,此外,我们可以提前处理出来所有链的$LCA$,这样可以省去许多时间

    参考代码如下:

      1 #pragma GCC optinize(3)
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cstring>
      5 #define N 600005
      6 using namespace std;
      7 int read()
      8 {
      9     int x=0,f=1;char ch=getchar();
     10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     11     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
     12     return x*f;
     13 }
     14 int n,m,v[N],w[N],head[N],nxt[N],cnt,fa[N][22],dep[N],maxn,_maxn,s[N],t[N],dist[N],lca[N],distt[N];
     15 int cf[N],scf[N];
     16 void dfs(int x,int f,int dis)
     17 {
     18     dep[x]=dep[f]+1;
     19     distt[x]=dis;
     20     for(int i=0;i<=19;i++)fa[x][i+1]=fa[fa[x][i]][i];
     21     for(int i=head[x];i;i=nxt[i])
     22     {
     23         if(v[i]==f)continue;
     24         fa[v[i]][0]=x;
     25         dfs(v[i],x,dis+w[i]);
     26     }
     27 }
     28 void dfs1(int x,int f)
     29 {
     30     scf[x]=cf[x];
     31     for(int i=head[x];i;i=nxt[i])
     32     {
     33         if(v[i]==f)continue;
     34         dfs1(v[i],x);
     35         scf[x]+=scf[v[i]];
     36     }
     37 }
     38 bool dfs2(int x,int f,int c,int len)
     39 {
     40     for(int i=head[x];i;i=nxt[i])
     41     {
     42         if(v[i]==f)continue;
     43         if(scf[v[i]]==c&&w[i]>=len)return 1;
     44         if(dfs2(v[i],x,c,len))return 1;
     45     }
     46     return 0;
     47 }
     48 int LCA(int x,int y)
     49 {
     50     if(dep[x]<dep[y])swap(x,y);
     51     for(int i=20;i>=0;i--)
     52     {
     53         if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
     54         if(x==y)return x;
     55     }
     56     for(int i=20;i>=0;i--)
     57     {
     58         if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
     59     }
     60     return fa[x][0];
     61 }
     62 void add(int a,int b,int c)
     63 {
     64     v[++cnt]=b;
     65     w[cnt]=c;
     66     nxt[cnt]=head[a];
     67     head[a]=cnt;
     68 }
     69 bool check(int x)
     70 {
     71     if(x>=_maxn)return 1;
     72     memset(cf,0,sizeof(cf));
     73     memset(scf,0,sizeof(scf));
     74     int _cnt=0;
     75     for(int i=1;i<=m;i++)
     76     {
     77         if(dist[i]>x)
     78         {
     79             _cnt++;
     80             cf[s[i]]++;cf[t[i]]++;
     81             cf[lca[i]]-=2;
     82         }
     83     }
     84     dfs1(1,0);
     85     return dfs2(1,0,_cnt,_maxn-x);
     86 }
     87 int main()
     88 {
     89     n=read();m=read();
     90     for(int x,y,z,i=1;i<n;i++)
     91     {
     92         x=read();y=read();z=read();
     93         maxn=max(maxn,z);
     94         add(x,y,z);add(y,x,z);
     95     }
     96     dfs(1,0,0);
     97     for(int i=1;i<=m;i++)
     98     {
     99         s[i]=read();t[i]=read();
    100         lca[i]=LCA(s[i],t[i]);
    101         dist[i]=distt[s[i]]+distt[t[i]]-2*distt[lca[i]]; 
    102         _maxn=max(_maxn,dist[i]);
    103     }
    104     int l=_maxn-maxn,r=_maxn+1,mid;
    105     while(l<=r)
    106     {
    107         mid=(l+r)>>1;
    108         if(check(mid))r=mid-1;
    109         else l=mid+1; 
    110     }
    111     printf("%d
    ",l);
    112     return 0;
    113 }
    [NOIP2015]运输计划
  • 相关阅读:
    实现selenium+Chrome爬取时不加载图片——配置
    对SHH的公钥和私钥的简单理解
    python正则匹配——中文字符的匹配
    学习笔记——TCP“三次握手”和“四次挥手”,简单介绍
    python在Linux中安装虚拟环境,区别python2和python3,分别安装模块
    Linux中安装MongoDB出现的问题记录
    PHP第三方登录——QQ登录
    OAuth2.0协议
    Shiro自动登录
    Shiro缓存管理
  • 原文地址:https://www.cnblogs.com/szmssf/p/11604774.html
Copyright © 2020-2023  润新知