zoukankan      html  css  js  c++  java
  • [bzoj1787]紧急集合

    对于三个点xyz,设a=lca(x,y),b=lca(x,z),不妨假设a的深度比b大,则ba的祖先(因为ax的祖先,b也是x的祖先)。

    首先将集合点定在a,考虑a向每一个方向调整,a向父亲调整会让xy答案加一,a向靠近x(y同理)的儿子调整,会让yz答案加一,向其他儿子调整,会让三者答案都加一,由此发现a是最合适的点(这个过程似乎并不是很严谨,可以理解就行)。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 500005
     4 struct ji{
     5     int nex,to;
     6 }edge[N<<1];
     7 int E,n,m,x,y,z,head[N],in[N],out[N],s[N],f[N][21];
     8 bool pd(int x,int y){
     9     return (in[x]<=in[y])&&(out[y]<=out[x]);
    10 }
    11 int lca(int x,int y){
    12     if (pd(x,y))return x;
    13     for(int i=20;i>=0;i--)
    14         if (!pd(f[x][i],y))x=f[x][i];
    15     return f[x][0];
    16 }
    17 int len(int x,int y){
    18     return s[x]+s[y]-2*s[lca(x,y)];
    19 }
    20 void add(int x,int y){
    21     edge[E].nex=head[x];
    22     edge[E].to=y;
    23     head[x]=E++;
    24 }
    25 void dfs(int k,int fa,int sh){
    26     in[k]=++x;
    27     s[k]=sh;
    28     f[k][0]=fa;
    29     for(int i=1;i<=20;i++)f[k][i]=f[f[k][i-1]][i-1];
    30     for(int i=head[k];i!=-1;i=edge[i].nex)
    31         if (edge[i].to!=fa)dfs(edge[i].to,k,sh+1);
    32     out[k]=++x;
    33 }
    34 int main(){
    35     scanf("%d%d",&n,&m);
    36     memset(head,-1,sizeof(head));
    37     for(int i=1;i<n;i++){
    38         scanf("%d%d",&x,&y);
    39         add(x,y);
    40         add(y,x);
    41     }
    42     x=0;
    43     dfs(1,1,0);
    44     for(int i=1;i<=m;i++){
    45         scanf("%d%d%d",&x,&y,&z);
    46         int k=(lca(x,y)^lca(x,z)^lca(y,z));
    47         printf("%d %d\n",k,len(x,k)+len(y,k)+len(z,k));
    48     }
    49 }
    View Code
  • 相关阅读:
    将深度学习低延迟推理性能提高一倍
    常量特征
    数据库链接笔记
    html5页面调用手机打电话功能
    插件使用一表单验证一validation
    插件使用一树形插件---zTree一zTree异步加载
    插件使用一树形插件---zTree
    插件使用一进度条---nprogress
    插件使用一颜色选择器---cxColor
    插件使用一顶部消息提示---overhang
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11249627.html
Copyright © 2011-2022 走看看