论求 $lca$ 最有效的方法是
作者:互联网
目录
\(standard\_table\) : 欧拉序 + \(ST\) 表
\(multiplication\) : 倍增
\(tree_chain_subdivision\) : 树链剖分
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n,m,rt,cnt;
vector <int> G[N];
namespace standard_table{
int dfn[N],dep[N],f[N*2][21];
inline void dfs(int x,int fa){
dep[x]=dep[fa]+1;
dfn[x]=++cnt;
f[cnt][0]=x;
for(auto y:G[x]){
if(y==fa) continue;
dfs(y,x);
f[++cnt][0]=x;
}
}
inline int lca(int x,int y){
int l=dfn[x],r=dfn[y];
if(l>r) swap(l,r);
int k=log2(r-l+1);
if(dep[f[l][k]]<=dep[f[r-(1<<k)+1][k]]) return f[l][k];
return f[r-(1<<k)+1][k];
}
inline void pre_work(){
cnt=0;
dfs(rt,0);
for(int j=1;(1<<j)<=cnt;++j)
for(int i=1;i+(1<<j)-1<=cnt;++i)
f[i][j]=dep[f[i][j-1]]<dep[f[i+(1<<j-1)][j-1]]?
f[i][j-1]:f[i+(1<<j-1)][j-1];
}
inline void solve(){
pre_work();
while(m--){
int x=read(),y=read();
printf("%d\n",lca(x,y));
}
}
}
//standard_table:35 lines
//time:O(2nlogn+m)
//space:O(2nlogn)
namespace multiplication{
int dep[N],f[N][20];
inline void dfs(int x,int fa){
dep[x]=dep[fa]+1,f[x][0]=fa;
for(int i=1;i<=19;++i)
f[x][i]=f[f[x][i-1]][i-1];
for(auto y:G[x])
if(y!=fa) dfs(y,x);
}
inline int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=19;i>=0;--i)
if(dep[f[x][i]]>=dep[y])
x=f[x][i];
if(x==y) return x;
for(int i=19;i>=0;--i)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
inline void solve(){
dfs(rt,0);
while(m--){
int x=read(),y=read();
printf("%d\n",lca(x,y));
}
}
}
//multiplication:28 lines
//time:O((n+m)logn)
//space:O(nlogn)
namespace tree_chain_subdivision{
int dep[N],son[N],top[N],dfn[N],sz[N],f[N];
inline void dfs1(int x,int fa){
dep[x]=dep[fa]+1,sz[x]=1,f[x]=fa;
int maxson=-1;
for(auto y:G[x]){
if(y==fa) continue;
dfs1(y,x);
sz[x]+=sz[y];
if(maxson<sz[y]) son[x]=y,maxson=sz[y];
}
}
inline void dfs2(int x,int tp){
top[x]=tp,dfn[x]=++cnt;
if(!son[x]) return;
dfs2(son[x],tp);
for(auto y:G[x])
if(y!=f[x]&&y!=son[x])
dfs2(y,y);
}
inline int lca(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=f[top[x]];
}
return dep[x]<dep[y]?x:y;
}
inline void solve(){
dfs1(rt,0);
dfs2(rt,rt);
while(m--){
int x=read(),y=read();
printf("%d\n",lca(x,y));
}
}
}
//tree_chain_subdivision:36 lines
//time:O(n+mlogn)
//space:O(n)
signed main(){
n=read(),m=read(),rt=read();
for(int i=1;i<n;++i){
int x=read(),y=read();
G[x].push_back(y);
G[y].push_back(x);
}
//standard_table::solve();
//multiplication::solve();
//tree_chain_subdivision::solve();
}
标签:dep,ch,fa,int,论求,有效,dfn,lca,inline 来源: https://www.cnblogs.com/into-qwq/p/16511238.html