D09 最近公共祖先(LCA)倍增算法

D09 最近公共祖先(LCA)倍增算法——信息学奥赛算法_哔哩哔哩_bilibili

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

1. f[u][0,1,2...] 维护 u 的各级祖先

2. dep[u] 维护 u 的深度

3. dfs(u,fa) 预处理 f[][],dep[]

4. lca(u,v) 先单跳,后双跳

// 倍增法 O(nlogn)
#include<bits/stdc++.h>
using namespace std;

const int N=500005;
int n,m,s;
vector<int> e[N];
int f[N][22],dep[N];

void dfs(int u,int fa){
  f[u][0]=fa; dep[u]=dep[fa]+1;
  for(int i=1;i<=20;i++) //u的2,4,8...祖先
    f[u][i]=f[f[u][i-1]][i-1];
  for(int v:e[u])
    if(v!=fa) dfs(v,u);
}
int lca(int u,int v){
  if(dep[u]<dep[v]) swap(u,v);
  for(int i=20;~i;i--) //u先大步后小步向上跳,直到与v同层
    if(dep[f[u][i]]>=dep[v]) u=f[u][i];
  if(u==v) return v;
  for(int i=20;~i;i--) //u,v一起向上跳,直到lca的下面
    if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
  return f[u][0];
}
int main(){
  scanf("%d%d%d",&n,&m,&s);
  for(int i=1,a,b; i<n; i++){
    scanf("%d%d",&a,&b);
    e[a].push_back(b);
    e[b].push_back(a);
  }
  dfs(s,0);
  for(int i=0,a,b;i<m;i++){
    scanf("%d%d",&a,&b);
    printf("%d\n",lca(a,b));
  }
}

 

最近公共祖先 - OI Wiki 

P4180 [BJWC2010] 严格次小生成树 - 洛谷

P10930 异象石 - 洛谷

 

posted @ 2022-05-28 13:23  董晓  阅读(4561)  评论(1)    收藏  举报