模板最近公共祖先(LCA)
Posted acm1ruoji
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板最近公共祖先(LCA)相关的知识,希望对你有一定的参考价值。
题目链接:https://www.luogu.org/problemnew/show/P3379
#include <bits/stdc++.h> using namespace std; #define ll long long #define re register #define fi first #define se second #define mp make_pair #define pb push_back #define P pair<int,int> const int N=5e5+10; const int mod=1e9+7; void read(int &a) { a=0; int d=1; char ch; while(ch=getchar(),ch>‘9‘||ch<‘0‘) if(ch==‘-‘) d=-1; a=ch-‘0‘; while(ch=getchar(),ch>=‘0‘&&ch<=‘9‘) a=a*10+ch-‘0‘; a*=d; } void write(int x) { if(x<0) putchar(45),x=-x; if(x>9) write(x/10); putchar(x%10+‘0‘); } int fa[N][20],head[N],num,dep[N],t; bool vis[N]; struct note { int to,next; }edge[2*N]; void add(int u,int v) { edge[++num].next=head[u]; edge[num].to=v; head[u]=num; } void dfs(int u,int h) { dep[u]=h; for(re int i=1;i<=t;i++) { if((1<<i)>=h) break; fa[u][i]=fa[fa[u][i-1]][i-1];///倍增核心算法 } for(re int i=head[u];i;i=edge[i].next) { if(!vis[edge[i].to]) { vis[edge[i].to]=1; fa[edge[i].to][0]=u; dfs(edge[i].to,h+1); } } } int LCA(int a,int b) { if(dep[a]<dep[b]) swap(a,b); int d=dep[a]-dep[b]; for(re int i=0;i<=t;i++) if((1<<i)&d)///跑去d有1的位置,可以避免减多而导致的回溯 a=fa[a][i];///跳去跟B同样的深度 if(a==b) return b; for(re int i=t;i>=0;i--) { if(!dep[fa[a][i]]) continue; if(fa[a][i]==fa[b][i]) continue; else a=fa[a][i],b=fa[b][i]; } return fa[a][0]; } int main() { int n,m,k; read(n); read(m); read(k); t=1.0*log2(n)+0.5;///算优化常数 for(re int i=0;i<n-1;i++) { int a,b; read(a); read(b); add(a,b); add(b,a); } vis[k]=1; fa[k][0]=k; dfs(k,1); while(m--) { int a,b; read(a); read(b); write(LCA(a,b)); putchar(‘ ‘); } return 0; }
以上是关于模板最近公共祖先(LCA)的主要内容,如果未能解决你的问题,请参考以下文章