P3379 模板最近公共祖先(LCA)(倍增LCA)

Posted wuliking

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3379 模板最近公共祖先(LCA)(倍增LCA)相关的知识,希望对你有一定的参考价值。

题目链接:https://www.luogu.org/problem/P3379

题目大意:

  给一棵以s为根的无向树,回答m个询问,回答出a和b最近的公共祖先。

解题报告:

  倍增LCA的模板题,用一个数组 f [i] [j]表示i结点的第$2^j$个祖先。显然,一个点的祖先是f[i][0],对于当前点的第$2^j$个祖先的第$2^j$个祖先,等于当前点的第$2^j+1$个祖先,因为$2^j+2^j=2^j+1$。所以有递推式$f[i][j]=f[f[i][j-1]][j-1]$

  还有一个常数优化是打表预处理出log2(i)+1的值。

AC代码:

 

技术图片
 1 #include<vector>
 2 #include<cstdio>
 3 #include<iostream>
 4 #include<cmath>
 5 #include<queue>
 6 #include<stack>
 7 #include<cmath>
 8 #include<algorithm>
 9 #define numm ch-48
10 #define pd putchar(‘ ‘)
11 #define pn putchar(‘\n‘)
12 #define pb push_back
13 #define fi first
14 #define se second
15 #define fre1 freopen("1.txt","r",stdin)
16 #define fre2 freopen("2.txt","w",stdout)
17 using namespace std;
18 template <typename T>
19 void read(T &res) 
20     bool flag=false;char ch;
21     while(!isdigit(ch=getchar())) (ch==-)&&(flag=true);
22     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
23     flag&&(res=-res);
24 
25 template <typename T>
26 void write(T x) 
27     if(x<0) putchar(-),x=-x;
28     if(x>9) write(x/10);
29     putchar(x%10+0);
30 
31 const int maxn=500010;
32 const int N=60;
33 const int inf=0x3f3f3f3f;
34 const int INF=0x7fffffff;
35 typedef long long ll;
36 struct node
37     int v,net;
38 e[maxn<<1];
39 int head[maxn],depth[maxn],lg[maxn],f[maxn][50],cnt;
40 void add(int u,int v) 
41     e[++cnt].v=v;
42     e[cnt].net=head[u];
43     head[u]=cnt;
44 
45 void dfs(int fath,int now) 
46     depth[now]=depth[fath]+1;
47     f[now][0]=fath;
48     for(int i=1;(1<<i)<=depth[now];i++)
49         f[now][i]=f[f[now][i-1]][i-1];
50     for(int i=head[now];i!=-1;i=e[i].net)
51         if(e[i].v!=fath) dfs(now,e[i].v);
52 
53 int lca(int x,int y) 
54     if(depth[x]<depth[y]) swap(x,y);
55     while(depth[x]>depth[y]) x=f[x][lg[depth[x]-depth[y]]-1];///x往父节点开始延伸
56     if(x==y) return x;  ///说明公共祖先为y,也就是当前的x
57     for(int i=lg[depth[x]]-1;~i;i--)
58         if(f[x][i]!=f[y][i])
59             x=f[x][i],y=f[y][i];
60     return f[x][0];
61 
62 int main()
63 
64     int n,m,s,a,b;
65     read(n),read(m),read(s);
66     fill(head+1,head+n+1,-1);
67     for(int i=1;i<=n-1;i++) 
68         read(a),read(b);
69         add(a,b),add(b,a);
70     
71     dfs(s,s);
72     for(int i=1;i<=n;i++)   ///常数优化,预处理求出log2[i]+1的值
73         lg[i]=lg[i-1]+(1<<lg[i-1]==i);
74     for(int i=1;i<=m;i++) 
75         read(a),read(b);
76         write(lca(a,b));pn;
77     
78     return 0;
79 
代码在这里!

 

 

 

 

 

以上是关于P3379 模板最近公共祖先(LCA)(倍增LCA)的主要内容,如果未能解决你的问题,请参考以下文章

[洛谷P3379]模板最近公共祖先(LCA)

luogo p3379 模板最近公共祖先(LCA)

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

最近公共祖先 倍增算法

LCA 最近公共祖先

P3379 模板最近公共祖先(LCA)(欧拉序+rmq)