zoukankan      html  css  js  c++  java
  • bzoj1787[Ahoi2008]Meet 紧急集合&bzoj1832[AHOI2008]聚会

    bzoj1787[Ahoi2008]Meet 紧急集合

    bzoj1832[AHOI2008]聚会

    题意:

    给个树,每次给三个点,求与这三个点距离最小的点。

    题解:

    倍增求出两两之间的LCA后,比较容易理解的做法是挑出两个LCA再做一次LCA,比较所有挑法。但画kan出ti图jie可知其中有两个LCA是相等的,而所求就是那个与它们不等的LCA(我也不知为什么)。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define maxn 500500
     5 #define inc(i,j,k) for(int i=j;i<=k;i++)
     6 using namespace std;
     7 
     8 inline int read(){
     9     char ch=getchar(); int f=1,x=0;
    10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    11     return x*f;
    12 }
    13 int fa[maxn][20],dep[maxn];
    14 struct e{int t,n;}; e es[maxn*2]; int g[maxn],ess;
    15 void pe(int f,int t){
    16     es[++ess]=(e){t,g[f]}; g[f]=ess; es[++ess]=(e){f,g[t]}; g[t]=ess;
    17 }
    18 void init(){ess=0; memset(g,0,sizeof(g));}
    19 void dfs(int x,int f){
    20     for(int i=g[x];i;i=es[i].n)if(es[i].t!=f){
    21         dep[es[i].t]=dep[x]+1; fa[es[i].t][0]=x; dfs(es[i].t,x);
    22     }
    23 }
    24 int n,m;
    25 void build(){
    26     for(int j=1;(1<<j)<=n;j++)inc(i,1,n)fa[i][j]=fa[fa[i][j-1]][j-1];
    27 }
    28 int lca(int x,int y){
    29     if(dep[x]<dep[y])swap(x,y); int t=dep[x]-dep[y];
    30     for(int i=0;(1<<i)<=n;i++)if(t&(1<<i))x=fa[x][i];
    31     for(int i=18;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    32     if(x==y)return x;else return fa[x][0];
    33 }
    34 int dis(int x,int y){
    35     int z=lca(x,y); return dep[x]-dep[z]+dep[y]-dep[z];
    36 }
    37 int main(){
    38     n=read(); m=read(); init(); inc(i,1,n-1){int a=read(),b=read(); pe(a,b);}
    39     dep[1]=0; fa[1][0]=0; dfs(1,0); build();
    40     inc(i,1,m){
    41         int a=read(),b=read(),c=read(); int x=lca(a,b),y=lca(a,c),z=lca(b,c);
    42         if(x==y)printf("%d %d
    ",z,dis(a,z)+dis(b,z)+dis(c,z));
    43         else if(x==z)printf("%d %d
    ",y,dis(a,y)+dis(b,y)+dis(c,y));
    44         else if(y==z)printf("%d %d
    ",x,dis(a,x)+dis(b,x)+dis(c,x));
    45     }
    46     return 0;
    47 }

    20160603

  • 相关阅读:
    Ext4文件系统架构分析(二)
    Ext4文件系统架构分析(一)
    STL容器与拷贝构造函数
    左值、右值与右值引用
    C++ 11右值引用
    读书笔记_Effective_C++_条款二十五: 考虑写出一个不抛出异常的swap函数
    《Effective C++》item25:考虑写出一个不抛异常的swap函数
    CC++ vector 构造函数 & 析构函数
    复制构造函数 与 赋值函数 的区别
    a++与++a
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/5689511.html
Copyright © 2011-2022 走看看