LCA

\(LCA\),即最近公共祖先,是指在有根树中,找出某两个结点\(u\)\(v\)最近的公共祖先

倍增法求\(LCA\),核心本质是让两个结点每次向上走2的幂次步

先处理出倍增数组\(fa\)\(fa[i][j]\)为从结点\(i\)向上走\(2^{j}\)步后能走到的结点

再将两个点移到同一深度

最后开始倍增来跳深度,应用了二进制拆分思想

时间复杂度为\(O(n\ log\ n)\)

\(code\):

void dfs(int x,int fath)
{
	de[x]=de[fath]+1;//求深度
	fa[x][0]=fath;
	for(int i=1;(1<<i)<=de[x];++i)
		fa[x][i]=fa[fa[x][i-1]][i-1];//初始化倍增
	for(int i=head[x];i;i=e[i].nxt)
	{
		int y=e[i].to;
		if(y==fath) continue;
		dfs(y,x);
	}
	return;
}
int lca(int x,int y)
{
	if(de[x]<de[y]) swap(x,y);
	for(int i=20;~i;--i)
		if(de[fa[x][i]]>=de[y])
			x=fa[x][i];
	if(x==y) return x;
	for(int i=20;~i;--i)
	{
		if(fa[x][i]!=fa[y][i])
		{
			x=fa[x][i];
			y=fa[y][i];
		}
	}
	return fa[x][0];
}

也可以用树链剖分求\(LCA\)

\(code\):

int lca(int x,int y)
{
	while(top[x]!=top[y])
	{
		if(de[top[x]]<de[top[y]]) swap(x,y);
		x=fa[top[x]];
	}
	if(dfn[x]>dfn[y]) swap(x,y);
	return x;
}
posted @ 2020-01-22 20:08  lhm_liu  阅读(160)  评论(0编辑  收藏  举报