• bzoj 1787: [Ahoi2008]Meet 紧急集合


    2016-06-22

    这个题就是找树中三个点到哪个点距离和最短,很明显是LCA,找这三个点两两之间的LCA,画个图看一下就行,很简单。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<queue>
     7 #define ll long long
     8 #define M 1000009
     9 using namespace std;
    10 ll read()
    11 {
    12     char ch=getchar();
    13     ll x=0,f=1;
    14     for(;ch<'0'||ch>'9';ch=getchar())
    15       if(ch=='-')
    16         f=-1;
    17     for(;ch>='0'&&ch<='9';ch=getchar())
    18       x=x*10+ch-'0';
    19     return x*f;
    20 }
    21 int n,m,cnt,h[M],head[M],next[M],u[M],lc[M][22];
    22 void jia(int a1,int a2)
    23 {
    24     next[++cnt]=head[a1];
    25     head[a1]=cnt;
    26     u[cnt]=a2;
    27 }
    28 void dfs(int x)
    29 {
    30     for(int i=1;(1<<i)<=h[x];i++)
    31       lc[x][i]=lc[lc[x][i-1]][i-1];
    32     for(int i=head[x];i;i=next[i])
    33       if(u[i]!=lc[x][0])
    34       {
    35           h[u[i]]=h[x]+1;
    36           lc[u[i]][0]=x;
    37           dfs(u[i]);
    38       }
    39 }
    40 int lca(int a1,int a2)
    41 {
    42     if(h[a1]<h[a2])
    43       swap(a1,a2);
    44     int a3=h[a1]-h[a2];
    45     for(int i=0;i<=20;i++)
    46       if(a3&(1<<i))
    47         a1=lc[a1][i];
    48     for(int i=20;i>=0;i--)
    49       if(lc[a1][i]!=lc[a2][i])
    50         {
    51             a1=lc[a1][i];
    52             a2=lc[a2][i];
    53         }
    54     if(a1==a2)
    55        return a1;
    56     return lc[a1][0];
    57 }
    58 int main()
    59 {
    60     n=read();
    61     m=read();
    62     for(int i=1;i<n;i++)
    63       {
    64         int a1=read(),a2=read();
    65         jia(a1,a2);
    66         jia(a2,a1);
    67       }
    68     dfs(1);
    69     for(int i=1;i<=m;i++)
    70       {
    71           int a1=read(),a2=read(),a3=read(),a4;
    72           int t1=lca(a1,a2),t2=lca(a1,a3),t3=lca(a2,a3);
    73         if(h[t2]<h[t1])
    74           printf("%d %d
    ",t1,h[a1]+h[a2]-h[t1]+h[a3]-2*h[t2]);
    75         else
    76           {
    77             if(h[t2]>h[t3])
    78               a4=t2;
    79             else
    80               a4=t3;
    81             printf("%d %d
    ",a4,h[a1]+h[a2]-2*h[t1]+h[a3]-h[a4]);    
    82           }
    83       }
    84     return 0;
    85 }
  • 相关阅读:
    Android 开发转型前端准备知识
    atom写文档技巧
    gerrit升级到16.04之后连接不到服务器
    adb shell am pm
    ArrayList和LinkedList的区别
    Android源码编译
    Android动态加载代码技术
    File 与 FileStream 文件运用
    物体在一定范围自有碰撞
    扫描二维码加载网页图片
  • 原文地址:https://www.cnblogs.com/xiw5/p/5605830.html
Copyright © 2020-2023  润新知