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

LCA(13,14)=12
LCA(13,7)=3
LCA(7,11)=2
LCA(11,2)=2
好了,了解以后我们就来康康怎么求吧
暴力LCA
如果找LCA(6,8),我们就要先让它们的深度相等。此时(deep[1]=0)deep[6]=4,deep[8]=3,我们就先让节点6爬到节点5
然后就是愉快的一起爬
让它们一层一层地向上爬,知道爬到同一节点
但是都知道,一旦这棵树有点高,like this,就会TTT

因为这样爬着太慢了(青蛙爬树都知道跳着爬)
倍增LCA
所以我们升级了,会跳着爬了
但是怎么升呢,大家都知道,计算机和二进制都离不开关系
所以当然是按照2的次方来跳,不过我们不是从小往大(1,2,4,8,16,32,64...),而是从大到小(...64,,32,16,8,4,2,1)(因为从小到大加着会超过,到时候很麻烦)
所以我们跳的时候就还要计算一下你这么跳会到哪个节点去(不然你乱跳啊)
总所周知,1+1=2(这不是废话吗)
1 void dfs(int x,int fa)
2 {
3 deep[x]=deep[fa]+1;
4 f[x][0]=fa;
5 for(int i=1;(1<<i)<=deep[x];i++)
6 {
7 f[x][i]=f[f[x][i-1]][i-1];
8 }
9 for(int i=0;i<mp[x].size();i++)
10 {
11 if(mp[x][i]==fa)continue;
12 dfs(mp[x][i],x);
13 }
14 }
我们用f[i][j]表示第i个节点向上跳2^j高度后的祖先节点,我们就不用像个憨批一样去搜了(不然你和暴力有什么区别),他就等于2^(j-1)*2也就是向上跳两次2^(j-1)
所以f[i][j]=f[f[i][]j-1][j-1]
所以我们循坏j从小到大,这样就可以用小的来递推大的了
然后搜索的时候顺便把深度也计算了
预处理完了,我们就要开始干正事了
1 int LCA(int x,int y)
2 {
3 if(deep[x]<deep[y])swap(x,y);
4 for(int i=log2(deep[x]);i>=0;i--)
5 if(deep[x]-(1<<i)>=deep[y])
6 x=f[x][i];
7 if(x==y)return x;
8 for(int i=log2(deep[x]);i>=0;i--)
9 {
10 if(f[x][i]!=f[y][i])
11 {
12 x=f[x][i];
13 y=f[y][i];
14 }
15 }
16 return f[x][0];
17 }
我们先让两个节点到达同一高度(为了方便计算,我们把高的放前面)
然后向上爬
先判断是否在同一点(因为存在两者的祖先是其中一个节点的可能,就是你和你爸的最近公共祖先是你爸)
然后一起向上跳跳跳(jump!!!)
为了避免两者计算出的公共祖先不是最近的(例如你爷爷也是你和你爸的公共祖先)
我们只跳到公共祖先的下一层,也就是第十排的判断
最后再输出它们的最近公共祖先就好了
1 #include<bits/stdc++.h>
2 #define N 500005
3 using namespace std;
4 int n,m,root;
5 int f[N][21];
6 int deep[N];
7 vector<int> mp[N];
8 inline int read(){
9 int x=0,f=1;
10 char ch=getchar();
11 while(ch<'0'||ch>'9'){
12 if(ch=='-')
13 f=-1;
14 ch=getchar();
15 }
16 while(ch>='0'&&ch<='9'){
17 x=(x<<1)+(x<<3)+(ch^48);
18 ch=getchar();
19 }
20 return x*f;
21 }
22 void dfs(int x,int fa)
23 {
24 deep[x]=deep[fa]+1;
25 f[x][0]=fa;
26 for(int i=1;(1<<i)<=deep[x];i++)
27 {
28 f[x][i]=f[f[x][i-1]][i-1];
29 }
30 for(int i=0;i<mp[x].size();i++)
31 {
32 if(mp[x][i]==fa)continue;
33 dfs(mp[x][i],x);
34 }
35 }
36 int LCA(int x,int y)
37 {
38 if(deep[x]<deep[y])swap(x,y);
39 for(int i=log2(deep[x]);i>=0;i--)
40 if(deep[x]-(1<<i)>=deep[y])
41 x=f[x][i];
42 if(x==y)return x;
43 for(int i=log2(deep[x]);i>=0;i--)
44 {
45 if(f[x][i]!=f[y][i])
46 {
47 x=f[x][i];
48 y=f[y][i];
49 }
50 }
51 return f[x][0];
52 }
53 int main()
54 {
55 deep[0]=-1;
56 n=read(),m=read(),root=read();
57 for(int i=1;i<n;i++)
58 {
59 int a,b;
60 a=read(),b=read();
61 mp[a].push_back(b);
62 mp[b].push_back(a);
63 }
64 dfs(root,0);
65 while(m--)
66 {
67 int a,b;
68 a=read(),b=read();
69 printf("%d\n",LCA(a,b));
70 }
71 return 0;
72 }