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

    传送门

    题目

    Input

    Output

    分析

    看到这个题不难想到倍增LCA,然后我们考虑如何计算。我们分别求出3个点中任意两点的LCA,为了走的步数最少所以肯定是先有两个点相遇然后另一个点走的它们相遇的点,至于最后的距离自己画一画就知道啦。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    #define ri register int
    const int LOG=18; 
    int pr[600000][LOG+3],dep[600000],cnt;
    int head[1200000],to[1200000],nxt[1200000];
    inline int read(){
          int x=0,f=1;char s=getchar();
          while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
          while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s-'0');s=getchar();}
          return x*f;
    }
    inline void add(int x,int y){
          to[++cnt]=y;
          nxt[cnt]=head[x];
          head[x]=cnt;
          to[++cnt]=x;
          nxt[cnt]=head[y];
          head[y]=cnt;
    }
    inline void dfs(int x,int fa){
          pr[x][0]=fa;
          for(ri i=head[x];i;i=nxt[i])
             if(to[i]!=fa){
               dep[to[i]]=dep[x]+1;
               dfs(to[i],x);
             }
    }
    inline int lca(int x,int y){
          if(dep[y]>dep[x])swap(x,y);
          int ans=0;
          for(ri i=LOG;i>=0;--i)
            if(dep[x]-(1<<i)>=dep[y])
              x=pr[x][i];
          if(x==y)return x;
          for(ri i=LOG;i>=0;--i)
            if(pr[x][i]!=pr[y][i]){
              x=pr[x][i];
              y=pr[y][i];
            }
          return pr[x][0];
    }
    int main()
    {     int n,m,x,y,z;
          n=read(),m=read();
          for(ri i=1;i<n;++i){
              x=read(),y=read();
              add(x,y);
          }
          dep[1]=1;
          dfs(1,0);
          for(ri j=1;j<=LOG;++j)
            for(ri i=1;i<=n;++i)
              pr[i][j]=pr[pr[i][j-1]][j-1];
          for(ri i=1;i<=m;++i){
              x=read(),y=read(),z=read();
              int a1=lca(x,y),a2=lca(x,z),a3=lca(y,z),ans;
              if(a1==a2)ans=a3;
                else if(a1==a3)ans=a2;
                else if(a2==a3)ans=a1;
              printf("%d %d
    ",ans,dep[x]+dep[y]+dep[z]-dep[a1]-dep[a2]-dep[a3]);
          }
          return 0;
    }
  • 相关阅读:
    Codevs堆练习
    codevs 3110 二叉堆练习3
    浅谈堆
    codevs 2924 数独挑战
    搜索技巧——持续更新
    2144 砝码称重 2
    codevs 2928 你缺什么
    codevs 2594 解药还是毒药
    codevs 2147 数星星
    判断素数
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/9205457.html
Copyright © 2011-2022 走看看