最近公共祖先LCA
P3379 【模板】最近公共祖先(LCA) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
倍增LCA
从两个点不断地向上跳,为了避免跳过和准确跳到,弹跳幅度逐渐减小,但要注意先使两个点的深度平齐,如此一块跳才能一块找到最近公共祖先
就如同两个实力相同的rabbits在比赛,为了比赛的公平性,先使距离终点远的rabbit到达同一距离,之后随之一声枪响,一块跳往终点,但rabbits的体力是有限的,因此越跳能跳的距离就越小,因此跳的越来越近(不要忘了远的rabbit到达起点后,要休息一阵,才开始比赛)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int lg=19; 4 const int N=500005*2; 5 int n,m,s,cnt; 6 int f[N][lg+1],deep[N],head[N]; 7 struct node 8 { 9 int to,nex; 10 }e[N]; 11 void add(int x,int y) 12 { 13 e[++cnt]=(node){y,head[x]}; 14 head[x]=cnt; 15 } 16 void dfs(int x) 17 { 18 for( int i=head[x];i;i=e[i].nex) 19 { 20 int t=e[i].to; 21 if(!deep[t]) 22 { 23 deep[t]=deep[x]+1; 24 f[t][0]=x; 25 dfs(t); 26 } 27 } 28 } 29 int lca(int x,int y) 30 { 31 if(deep[x]<deep[y])swap(x,y); 32 for(int i=lg;i>=0;--i) 33 { 34 if(deep[f[x][i]]>=deep[y]) 35 x=f[x][i]; 36 } 37 if(x==y)return y; 38 for(int i=lg;i>=0;--i) 39 { 40 if(f[x][i]!=f[y][i]) 41 { 42 x=f[x][i]; 43 y=f[y][i]; 44 } 45 } 46 return f[x][0]; 47 } 48 int main() 49 { 50 cin>>n>>m>>s; 51 for(int i=1;i<=n-1;++i) 52 { 53 int x,y; 54 cin>>x>>y; 55 add(x,y); 56 add(y,x); 57 } 58 deep[s]=1; 59 dfs(s); 60 for(int j=1;j<=lg;++j) 61 for(int i=1;i<=n;++i) 62 { 63 f[i][j]=f[f[i][j-1]][j-1]; 64 } 65 for(int i=1;i<=m;++i) 66 { 67 int a,b; 68 cin>>a>>b; 69 cout<<lca(a,b)<<endl; 70 } 71 return 0; 72 }