树链剖分求LCA(洛谷P3379)

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+10;
vector<int>g[maxn];
int head[maxn],tot;
void add(int fr,int to){
    g[fr].push_back(to);
    g[to].push_back(fr);
}
int size[maxn];//子树大小
int fath[maxn];//
int maxson[maxn];//
int depth[maxn];
void dfs1(int u,int fa){
    depth[u]=depth[fa]+1;
    fath[u]=fa;
    size[u]++;
    int maxsize=0;
    for(int i=0;i<g[u].size();i++){
        int v=g[u][i];
        if(v==fa)continue;
        dfs1(v,u);
        size[u]+=size[v];
        if(maxsize<size[v]){maxsize=size[v];maxson[u]=v;}
    }
}
int dfn[maxn];int thehead[maxn];
int totdfn=0;
void dfs2(int u,int fa,int _head){
    dfn[u]=++totdfn;
    thehead[u]=_head;
    if(!maxson[u])return;
    dfs2(maxson[u],u,_head);
    for(int i=0;i<g[u].size();i++){
        int v=g[u][i];
        if(v==fa)continue;
        if(v==maxson[u])continue;
        dfs2(v,u,v);
    }
}
int lca(int c,int d){
    while(thehead[c]!=thehead[d]){
        if(depth[thehead[c]]<depth[thehead[d]]){//d c>>d d
            swap(c,d);
        };
        c=fath[thehead[c]];
    }
    if(depth[c]>depth[d])return d;
    else return c;
}
int n,m,root;
signed main(){
    //freopen("C:\Users\11631\Desktop\P3379_2.in","r",stdin);
    cin>>n>>m>>root;
    for(int i=1;i<=n-1;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
    }
    dfs1(root,0);
    dfs2(root,0,root);
    while(m--){
        int a,b;
        scanf("%d%d",&a,&b);
        cout<<lca(a,b)<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/yesuweiYYYY/p/13809367.html