最近公共祖先LCA
若两个节点的祖先相同,则叫该节点的公共祖先
简称LCA
显然,两个节点的LCA只有一个,且一定是两个点到根的路径中重复部分最下端的点
算法1(暴力法):
-
求出每一个结点的深度
-
询问两个节点是否重合,若重合,则LCA已求出
-
否则,选择两个点中深度较大的点,并移动到他的父亲
-
重复执行2,3步
上图的执行流程如下:- 两个指针位于3与9。
- 此时9节点深度较大,向上移动到它的父亲7
- 此时两个节点深度一样,移动3到他的父亲1
- 此时7深度较大,向上移动到5号节点
- 此时两个节点深度一样,移动1到0
- 此时5深度较大,向上移动到0,两个指针重合,0为LCA.
算法代码如下
int de[MAXN],fa[MAXN];
void dfs(int x,int fath)//遍历这棵树并求出每个点的深度和父亲
{
fa[x]=fath;de[x]=de[fath]+1;
for(int i=fi[x];i;i=ne[i])
if(to[i]!=fath)dfs(to[i],x);
}
int getlca(int x,int y)//求LCA
{
while(x!=y)
{
//将节点深度较大的点的指针往上移动
if(de[x]>=de[y])
x=fa[x];
else
y=fa[y];
}
return x;
}
暴力法 | |
---|---|
时间复杂度 | O(nq) |
优点 | 容易理解和实现,存储空间小,支持动态的树 |
缺点 | 最坏情况下时间复杂度很高 |