Loading

「学习笔记」树链剖分求LCA

前言

我在洛谷 【模板】最近公共祖先(LCA)上比较了倍增求法与树剖求法
image
至少评测结果表明树链剖分求lca更快 蒟蒻不会分析时间复杂度

进入正题

lca:树上两个点的最近公共祖先
可以用倍增、树剖、tarjan、dfs 序、以及暴力来求,倍增我有写,tarjan 等会了再说
首先,还是树剖的两个最基本的 dfs,但是相较于一般的维护或修改链上的那种树剖,只是求 lca 的树剖就不用维护那么多信息了 当然了,最最基本的还是要维护的
先上两遍 dfs 的代码:

void dfs(int u, int fat) {
	dep[u] = dep[fat] + 1;
	fa[u] = fat;
	siz[u] = 1;
	for(int i = h[u]; i; i = e[i].nxt) {
		int v = e[i].v;
		if(v == fat)	continue;
		dfs(v, u);
		siz[u] += siz[v];
		if(siz[v] > siz[son[u]])	son[u] = v;
	}
}

void getpos(int u, int tp) {
	top[u] = tp;
	if(!son[u])	return ;
	getpos(son[u], tp);
	for(int i = h[u]; i; i = e[i].nxt) {
		int v = e[i].v;
		if(v == fa[u] || v == son[u])	continue;
		getpos(v, v);
	}
}

准备工作做完后,我们开始求 lca
在树剖中,如果两个点不在一条链上,即它们的链顶不同,那就往上跳,直到跳到一条链上
当两个点在一条链上时,深度更浅的点就是 lca
代码:

ll lca(int a, int b) {
	while(top[a] != top[b]) {
		if(dep[top[a]] < dep[top[b]])	swap(a, b);
		a = fa[top[a]];
	}
	if(dep[a] < dep[b])	return a;
	return b;
}

结束

posted @ 2022-08-13 14:53  yi_fan0305  阅读(15)  评论(0编辑  收藏  举报