• 学习算法——最近公共祖先

  • 算法介绍:LCA(Least Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先。 ———来自百度百科

  • 例题:洛谷-LCA模板题

  • 模板代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 500005;
struct node{
    int t,nex;
};
node a[maxn<<1];
int head[maxn],tot;
void add(int x,int y){
    a[++tot].t = y,a[tot].nex = head[x],head[x] = tot;
}

int depth[maxn],fa[maxn][30],lg[maxn];
void dfs(int x,int fath)
{
    fa[x][0] = fath,depth[x] = depth[fath] + 1;
    for(int i=1;i<=lg[depth[x]];i++)
        fa[x][i] = fa[fa[x][i-1]][i-1];
    for(int i=head[x] ; i ; i = a[i].nex)
        if(a[i].t != fath)
            dfs(a[i].t , x);
}
int lca(int x,int y)
{
    if(depth[x] < depth[y])swap(x,y);
    while(depth[x] > depth[y])
        x = fa[x][lg[depth[x]-depth[y]] -1];
    if(x == y)
        return x;
    for(int k=lg[depth[x]] - 1;k>=0;k--)
        if(fa[x][k] != fa[y][k])
            x = fa[x][k] , y = fa[y][k];
    return fa[x][0];
}
int main()
{
    int n,m,s;
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y),add(y,x);
    }
    for(int i=1;i<=n;i++)
        lg[i] = lg[i-1] + (1<<lg[i-1] == i);
    dfs(s , 0);
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        printf("%d\n",lca(x,y));
    }
    return 0;
}