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

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

  • 时空限制1s / 512MB

题目描述

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

输入输出格式

输入格式:

 

第一行包含三个正整数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。

----------------------------------------------------------------------------------------------------------------

注意题目中的边是无向的,所以要建双向,所以边数应为m*2,需要开两倍数组(我没注意只开了一倍就蠢蠢地submit结果。。。)

这里的倍增+LCA

把表示幂的一维放到前面

就是把小的一维放到前面

会对内存友好

听说就会快很多 

 

存板子:

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 #define maxn 500010
 5 using namespace std;
 6 struct node{
 7     int to,next;
 8 };
 9 node e[maxn<<1];
10 int read();
11 int n,m,s,pre[maxn],cnt,len[maxn],p[23][maxn];
12 bool po[maxn];
13 int lca(int,int);
14 void dfs(int);
15 void ycl();
16 void build(int,int);
17 int main(){
18     memset(po,0,sizeof(po));
19     n=read();m=read();s=read();
20     cnt=0;
21     for(int i=1;i<n;i++){
22         int x=read(),y=read();
23         build(x,y);
24     }
25     len[s]=1;po[s]=1;
26     dfs(s);
27     ycl();
28     for(int i=1;i<=m;i++){
29         int x=read(),y=read();
30         printf("%d\n",lca(x,y));
31     }
32     return 0;
33 }
34 int lca(int x,int y){
35     if(len[x]>len[y]) swap(x,y);
36     int k=len[y]-len[x];
37     for(int j=0;(1<<j)<=k;j++)
38     if((1<<j)&k) y=p[j][y];
39     if(x==y) return x;
40     for(int j=21;j>=0;j--)
41        if(p[j][x]!=p[j][y]){
42            x=p[j][x];
43            y=p[j][y];
44        }
45     return p[0][y];
46 }
47 void dfs(int x){
48     for(int i=pre[x];i;i=e[i].next){
49         int to=e[i].to;
50         if(!po[to]){
51             po[to]=1;
52             len[to]=len[x]+1;
53             p[0][to]=x;
54             dfs(to);
55         }
56     }
57 }
58 void ycl(){
59     for(int j=1;(1<<j)<=n;j++)
60        for(int i=1;i<=n;i++)
61        p[j][i]=p[j-1][p[j-1][i]];
62 }
63 void build(int x,int y){
64     e[++cnt].to=y;e[cnt].next=pre[x];pre[x]=cnt;
65     e[++cnt].to=x;e[cnt].next=pre[y];pre[y]=cnt;
66 }
67 int read(){
68     int ans=0,f=1;char c=getchar();
69     while('0'>c||c>'9'){if(c=='-')f=-1;c=getchar();}
70     while('0'<=c&&c<='9')ans=ans*10+c-48,c=getchar();return ans*f;
71 }
倍增+LCA

 

posted @ 2017-11-09 22:32  lpl_bys  阅读(248)  评论(0编辑  收藏  举报