LCA之倍增法(例题:POJ1330)

本文介绍了如何利用倍增法求解一棵树中两个节点的最近公共祖先(LCA)。首先概述了倍增法求LCA的整体流程,包括预处理和计算步骤,并解释了算法原理。接着给出了一个具体的例题——POJ1330,详细解析了题目要求,并附带了算法模板。最后,展示了输入输出样例和解题思路。
摘要由CSDN通过智能技术生成

LCA之倍增法

最近公共祖先简称 LCA(Lowest Common Ancestor)。两个节点的最近公共祖先,就是这两个点的公共祖先里面,离根最远的那个。

除去朴素算法,LCA还可以用倍增法来求,倍增法在算法中的应用还是比较多的,可以用来求ST表(区间最大最小值),还可以用来求LCA。其中求LCA的方法如下:

整体流程

预处理

用BFS或者DFS处理

  1. deg[i]:结点i的深度
  2. fa[i][j]:每个结点往上跳2^j后的位置
  3. tu,tv为跳到的位置

计算

假设求u和v的LCA,核心就只有两步

  1. 将u和v先跳到同一层
  2. u和v同时往上跳
  3. 跳的时候总是跳2 ^ j个,从大到小跳(判断能不能跳,能跳就跳)
  4. 最后返回fa[tu][0]

原理

我们假设u跳到LCA的距离为Len,因为Len可以用二进制表示,也就是说Len可以拆分为很多个2的倍数,所以我们每次跳2的j次个一定可以跳到LCA,同时我们跳的次数的复杂度就是logn的复杂度。
关于判断我们选择的j次是不是要跳的,我们可以判断跳了2的j次以后所在的位置,如果他俩相等说明跳多了,因为我们最后的结果是跳到LCA的下一个,所以他们一定不会相等,相等即说明跳多了。
看一下模板里面的具体实现可以更加清楚一点。

模板

copy from kuangbin

const int MAXN=10010;
// 跳转的大小,可以手动调大
const int DEG=20;

// 链式前向星部分
struct Edge{
   
    int to,next;
}edge[MAXN*2];
int head[MAXN],tot;
void addedge(int u,int v) {
   
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void init() {
   
    tot=0;
    memset(head,-1,sizeof(head));
}

// fa[i][j]表示结点i的第2^j个祖先
int fa[MAXN][DEG];
// 深度数组
int deg[MAXN];

// 标记深度,预处理fa数组
void BFS(int root) {
   
    queue<int>que;
    deg[root]=0;
    fa[root][0]=root;
    que.push(root);
    while(!que.empty()) {
   
        int tmp=que.front();
        que.pop();
        for (int i=1;i<DEG;i++)
            fa[tmp][i]=fa[fa[tmp][i-1]][i-1];
        for (int i
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值