zoukankan      html  css  js  c++  java
  • 【LCA】BZOJ1832 & BZOJ1787(AHOI)-集会

    【题目大意】

    一个图有n个点n-1条边(也就是说是一棵树),求其中三点共同到达某一点经过总共的最少边数以及共同到达的那一点。

    【思路】

    借用一下黄学长给的结论:三个点两两取LCA,其中必有两个相同,则另外一个点就是答案。

    注意BZOJ大数据要用scanf和printf,因为cout的原因RE了好几次_(:зゝ∠)_基本算是一道标程类的题目了啦。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cmath>
      5 #include<cstring>
      6 #include<algorithm>
      7 #include<vector>
      8 const int MAXN=500001;
      9 const int M=20;
     10 using namespace std;
     11 int n,m;
     12 vector<int> G[MAXN];
     13 int fa[MAXN][M];
     14 int dep[MAXN];
     15 
     16 void dfs(int v,int p,int d)
     17 {
     18     fa[v][0]=p;
     19     dep[v]=d;
     20     for (int i=0;i<G[v].size();i++)
     21         if (G[v][i]!=p) dfs(G[v][i],v,d+1);
     22 }
     23 
     24 void kb()
     25 {
     26     for (int i=1;i<M;i++)
     27         for (int j=1;j<=n;j++)
     28         {
     29             fa[j][i]=fa[fa[j][i-1]][i-1];
     30         }
     31 }
     32 
     33 void init()
     34 {
     35     scanf("%d%d",&n,&m);
     36     for (int i=0;i<n-1;i++)
     37     {
     38         int fr,to;
     39         scanf("%d%d",&fr,&to);
     40         G[fr].push_back(to);
     41         G[to].push_back(fr);
     42     }
     43     dfs(1,0,0);
     44     kb();
     45 }
     46 
     47 int swim(int x,int H)
     48 {
     49     for (int i=0;H>0;i++)
     50     {
     51         if (H&1) x=fa[x][i];
     52         H/=2;
     53     }
     54     return x;
     55 }
     56 
     57 int LCA(int u,int v)
     58 {
     59     if (dep[u]<dep[v]) swap(u,v);
     60     u=swim(u,dep[u]-dep[v]);
     61     if (u==v) return u;
     62     for (int i=M-1;i>=0;i--)
     63     {
     64         if (fa[u][i]!=fa[v][i])
     65         {
     66             u=fa[u][i];
     67             v=fa[v][i];
     68         }
     69     }
     70     return fa[u][0];
     71 }
     72 
     73 int dis(int x,int y)
     74 {
     75     int z=LCA(x,y);
     76     int re=dep[x]+dep[y]-2*dep[z];
     77     return re;
     78 }
     79 
     80 void query()
     81 {
     82     int u,v,w;
     83     for (int i=0;i<m;i++)
     84     {
     85         scanf("%d%d%d",&u,&v,&w);
     86         int uv=LCA(u,v);
     87         int uw=LCA(u,w);
     88         int vw=LCA(v,w);
     89         int pos;
     90         if (uv==uw) pos=vw;
     91             else if (uv==vw) pos=uw;
     92                 else pos=uv;
     93          int cost=dis(u,pos)+dis(v,pos)+dis(w,pos);
     94          printf("%d %d
    ",pos,cost);
     95     }
     96 }
     97 
     98 int main()
     99 {
    100     init();
    101     query();
    102     return 0;
    103 }
  • 相关阅读:
    静态连接库
    03数据的增删改查
    02MySQL中的数据类型
    01MySQL的 库、表初步认识
    Python 函数
    Linux系统目录结构
    Linux系统启动过程
    第三章 Web页面建设
    《第二章:深入了解超文本》
    《HTML与CSS 第一章 认识HTML》读书笔记
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5138009.html
Copyright © 2011-2022 走看看