树链剖析求LCA

树链剖析求LCA

一 LCA问题

 LCA问题即树上最近公共祖先,求解LCA问题经典的解法有倍增,tarjan(万能的Tarjan),当然还有我们的树链剖析了

二 前置芝士

在求解lCA之前,我们要知道树链剖析的一些基础知识,在树链剖析中分为轻重链剖析和长短链剖析

重点:相依值最大的一个点(可以是根据子树的大小或者子树的深度进行选择),每一个点的子节点只有一个重节点

轻节点:除重点之外的节点都是轻节点

重链:指的是重点和其父节点相连的那个边

轻链:指的是轻节点和其父节点相连的那个边

顶点:指的是沿重链回溯到最前的那个顶点,遇到轻链便终止,所以轻节点的顶点就是它的本身

三 思路

 在进行两个点的查询时候,如果两个节点的顶点不同,说明这两个点不在一条链上,此时我们需要让深度较深的那个点跳转到它的顶点的父节点,重复上面的操作,知道两个顶点跳转到一条链上,输出深度较浅的那个点。

 当两个点的顶点不同的时候,两个点不在一条链上,如果使得次点为其顶点的父节点,才有可能在一条链上,并且是不会超过的,因为父节点只是向上增加一个位置,而两个不在一条链,起码是存在一个位置以上的差距。当两个点在一条链上时,前面的点一定是他们的LCA

6011632897515_.pic

四 code

1 求重链和重点

void DFS1(int x)
{
    size[x] = 1;
    dep[x] = dep[f[x]] + 1;
    for(int i = head[x];i;i = E[i].next){
        int to = E[i].to;
        if(to == f[x]) continue;
        f[to] = x;
        DFS1(to);
        size[x] += size[to];
        if(!son[x]||size[son[x]] < size[to]) son[x] = to;
        // son[x]是这个x的最重子节点
    }
}

2 求顶点

void DFS2(int x,int tv)
{
    top[x] = tv;
    if(son[x]) DFS2(son[x],tv);
    for(int i = head[x];i;i = E[i].next)
    {
        int to = E[i].to;
        if(to == f[x]||to == son[x]) continue;
        DFS2(to,to);
    }
}

3 LCA

while (top[x]!=top[y])
{
     if(dep[top[x]] >= dep[top[y]]) x = f[top[x]];
      else y = f[top[y]];
}
printf("%d\n",dep[x]<dep[y]?x:y);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值