LCA 问题 + 模板

Posted 在那遥远的悠穹下

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LCA 问题 + 模板相关的知识,希望对你有一定的参考价值。

LCA

LCA 的问题是很经典的,我这一次就来讲解一下 LCA 的求法,就先从一道模板题入手吧

题目

P3379 【模板】最近公共祖先(LCA)

输入格式

第一行包含三个正整数 \\(N,M,S\\) 分别表示树的结点个数、询问的个数和树根结点的序号。

接下来 \\(N-1\\) 行每行包含两个正整数 \\(x, y\\) 表示 \\(x\\) 结点和 \\(y\\) 结点之间有一条直接连接的边(数据保证可以构成树)。

接下来 \\(M\\) 行每行包含两个正整数 \\(a, b\\) 表示询问 \\(a\\) 结点和 \\(b\\) 结点的最近公共祖先。

输出格式

输出包含 \\(M\\) 行,每行包含一个正整数,依次为每一个询问的结果。

说明/提示

对于 \\(30\\%\\) 的数据,\\(N\\leq 10,N \\leq 10\\)

对于 \\(70\\%\\) 的数据,\\(N\\leq 10000,N \\leq 10000\\)

对于 \\(100\\%\\) 的数据,\\(N\\leq 500000 , N \\leq 500000\\)

方法

朴素算法

首先,我们想到最暴力的方法,先把整个树 DFS 一下,顺便将每个点的深度记录下来,将要查找的两个点中每次找深度最大的点,然后向上跳一格,最后两个点一定会相遇,相遇的点就一定是他们的 LCA 。

下面是 DFS 的代码

void dfs(int u,int fa){     // fa 为父亲节点,u 为当前节点, dep 为节点深度
	f[u] = fa;
	dep[u] = dep[fa] + 1;   // 因为是 DFS ,每个节点是从它的父亲来的,父亲与儿子的深度相差 1 
	for(int i=head[u];i;i = nex[i]){        // 链式前向星
		int v = to[i]; 
		if(v != fa)
			dfs(v,u);
	}
}

以上是关于LCA 问题 + 模板的主要内容,如果未能解决你的问题,请参考以下文章

POJ 1330(LCA模板)

模板 倍增lca

POJ 1470 Closest Common Ancestors (模板题)(Tarjan离线)LCA

LCA 问题 + 模板

[jzyzoj2021]lca模板题

P3379 模板最近公共祖先(LCA)