其他分享
首页 > 其他分享> > 论求 $lca$ 最有效的方法是

论求 $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