DFS 序 O(1) 求 LCA

更新日志 2025/11/03:开工。

思路

查询 \((dfn_u,dfn_v]\) 最小深度的节点的父亲即可。读者自证不难。

代码

例题

const int N=5e5+5,T=20;

int n,m,s;
vec<int> g[N];
int dcnt,dfn[N],dp[N];
int st[N][T],lg[N];
void dfs(int x,int fa){
    dp[x]=dp[fa]+1;
    dfn[x]=++dcnt,st[dfn[x]][0]=fa;
    for(auto y:g[x])if(y!=fa)dfs(y,x);
}
inline int lca(int a,int b){
    if(a==b)return a;
    a=dfn[a],b=dfn[b];if(a>b)swap(a,b);++a;
    int t=lg[b-a+1];
    return (dp[st[a][t]]<dp[st[b-(1<<t)+1][t]]?st[a][t]:st[b-(1<<t)+1][t]);
}

inline void Main(){
	cin>>n>>m>>s;
    rep(i,2,n)lg[i]=lg[i>>1]+1;
    repl(i,1,n){
        int a,b;cin>>a>>b;
        g[a].pub(b),g[b].pub(a);
    }
    dfs(s,0);
    repl(t,1,T)rep(i,1,n-(1<<t)+1)st[i][t]=(dp[st[i][t-1]]<dp[st[i+(1<<t-1)][t-1]]?st[i][t-1]:st[i+(1<<t-1)][t-1]);
    rep(i,1,m){
        int a,b;cin>>a>>b;
        put(lca(a,b));
    }
}
posted @ 2025-11-03 19:06  LastKismet  阅读(2)  评论(0)    收藏  举报