洛谷P3379 【模板】最近公共祖先(LCA)

题目描述

如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。

输入输出格式

输入格式:

第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。

接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。

接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。

输出格式:

输出包含M行,每行包含一个正整数,依次为每一个询问的结果。

输入输出样例

输入样例#1:
5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5
输出样例#1:
4
4
1
4
4

说明

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=10,M<=10

对于70%的数据:N<=10000,M<=10000

对于100%的数据:N<=500000,M<=500000

样例说明:

该树结构如下:

第一次询问:2、4的最近公共祖先,故为4。

第二次询问:3、2的最近公共祖先,故为4。

第三次询问:3、5的最近公共祖先,故为1。

第四次询问:1、2的最近公共祖先,故为4。

第五次询问:4、5的最近公共祖先,故为4。

故输出依次为4、4、1、4、4。

  1 #include<iostream>
  2 #include<cstdio>
  3 
  4 using namespace std;
  5 const int N=1000001;
  6 
  7 struct node{
  8     int u,v,nxt;
  9 }E[N];
 10 
 11 int head[N];
 12 int n,m,r;
 13 int now=1;
 14 int D[N];
 15 int f[N][20];
 16 
 17 inline void add(int u,int v)
 18 {
 19     E[now].u=u;
 20     E[now].v=v;
 21     E[now].nxt=head[u];
 22     head[u]=now++;
 23 }
 24 
 25 inline void read(int & x)
 26 {
 27     char c=getchar();
 28     x=0;
 29     while(c<'0'||c>'9')c=getchar();
 30     while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
 31 }
 32 
 33 inline void build_T(int r)
 34 {
 35     for(int i=head[r];i!=-1;i=E[i].nxt)
 36     {
 37         int v=E[i].v;
 38         if(!D[v])
 39         {
 40             D[v]=D[r]+1;
 41             f[v][0]=r;
 42             build_T(v);
 43         }
 44     }
 45 }
 46 
 47 inline void build_ST()
 48 {
 49     for(int i=1;i<=19;i++)
 50     {
 51         for(int j=1;j<=n;j++)
 52         {
 53             f[j][i]=f[f[j][i-1]][i-1];
 54         }
 55     }
 56 }
 57 
 58 inline int LCA(int x,int y)
 59 {
 60     if(D[x]<D[y])swap(x,y);
 61     for(int i=19;i>=0;i--)
 62     {
 63         if(D[f[x][i]]>=D[y])
 64         {
 65             x=f[x][i];
 66         }
 67     }
 68     if(x==y)return y;
 69     for(int i=19;i>=0;i--)
 70     {
 71         if(f[x][i]!=f[y][i])
 72         {
 73             x=f[x][i];
 74             y=f[y][i];
 75         }
 76     }
 77     return f[x][0];
 78 }
 79 
 80 int main()
 81 {
 82     read(n);read(m);read(r);
 83     
 84     for(int i=1;i<=n;i++)
 85        head[i]=-1;
 86     for(int i=1;i<=n-1;i++)
 87     {
 88         int u,v;
 89         read(u);
 90         read(v);
 91         add(u,v);
 92         add(v,u);
 93     }
 94     D[r]=1;
 95     build_T(r);
 96     build_ST();
 97     
 98     for(int i=1;i<=m;i++)
 99     {
100         int x,y;
101         read(x);
102         read(y);
103         printf("%d\n",LCA(x,y));
104     }
105     
106 }

 

posted @ 2017-05-14 17:32  ioioioioioio  阅读(162)  评论(0编辑  收藏  举报