LCA(最近公共祖先)(2.14)

定义:LCA,即最近公共祖先,是指在在有根树中,找到两个节点的最近公共祖先。

如图,4和7的最近公共祖先是2。

如何求最近公共祖先:

1:两点同时网上走并标记,若第一次一个点走到被标记过得点,那个点就是最近公共祖先;

2:深度高的点先往上走,直到两点深度一样就一起往上走。

代码:

3.倍增法:

注意到uv走到最近公共祖先w之前,uv所在结点不相同。而到达最近公共祖先w后,再往上走仍是uv的公共祖先,即uv走到同一个结点,这具有二分性质。于是可以预处理出一个2k的表,fa[k][u]表示u往上走2k步走到的结点,令根结点深度为0,则2k>depth[u]时,令fa[k][u]=-1(不合法情况的处理)。不妨假设depth[u] < depth[v]①将v往上走d = depth[v] - depth[u]步,此时uv所在结点深度相同,该过程可用二进制优化。由于d是确定值,将d看成2的次方的和值d = 2k1 + 2k2 + ... + 2km,利用fa数组如v = fa[k1][v]v = fa[k2][v]加速。

②若此时u = v,说明Lca(u,v)已找到

③利用fa数组加速uv一起往上走到最近公共祖先w的过程。令d = depth[u] - depth[w],虽然d是个未知值,但依然可以看成2的次方的和。从高位到低位枚举d的二进制位,设最低位为第0位,若枚举到第k位,有fa[k][u] != fa[k][v],则令u = fa[k][u]v = fa[k][v]。最后最近公共祖先w = fa[0][u] = fa[0][v],即uv的父亲。

倍增如何预处理:k=0时,fa[k][u]为u在有根树的父亲,令fa[k][root]=-1;k>0时,fa[k][u]=fa[k-1][fa[k-1][u]];

时间复杂度:预处理o(nlogn);单词查询o(longn);

tarjan离线算法:

离线算法是把所有询问储存下来,一次处理全部,求得答案。tarjian算法就是这样,要找两个点a,b的最近公共祖先,先dfs从a点遍历到b点。遍历到b时,路劲上除了外节点的子树都遍历过了,而子树没遍历完,对于a,访问完他的子树后就在a的并查集中的父亲设为他在树中的父亲,访问b是b在a并查集中的父亲就是最a和b的近公共祖先。

这样依次更新,bfs,知道发现1诶呦被搜过的点也没有关系点就退出。

程序实现:

 

 

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值