欲望以提升热忱,毅力以磨平|

XichenOC

园龄:1个月粉丝:4关注:0

2025-01-20 19:11阅读: 16评论: 0推荐: 0

最近公共祖先LCA(学习笔记)

\(LCA\)

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

定义:

在一棵树上,任意两个节点,往上找的最近的公共根节点就是他们两个的最近公共祖先\(LCA\)

作用:

可用于求树上任意两个点的路径和其路径的权值关系,如边权最大值,边权和等,都是以\(logn\)的复杂度

实现:

倍增:

倍增,顾名思义,运用了指数打表的思想。

1.我们要用\(dfs\)遍历每一点,预处理求出每一节点的\(i\)次倍后的父亲节点,及\(f_{x,i}\)表示点\(x\)\(2^i\)个祖先,并且找到每一个节点的深度

void dfs(int u,int fa){
    d[u]=d[fa]+1;
    f[u][0]=fa;
    for(int i=1;(1<<i)<=d[u];i++)f[u][i]=f[f[u][i-1]][i-1];
    for(int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if(v==fa)continue;
        dfs(v,u);
    }
}

2.倍增求\(LCA\)时,我们先要确保要找的点在同一深度。让后一起向上跳求\(LCA\)。因此先要判断两节点的深度,在将深的往上跳,直到跳到同一深度。这时要判断是否相等,预防一个节点就是另一节点的根节点。相等则直接返回


3.等两节点在同一高度后,在同时向上跳,知道跳完,这是,两节点所在节点就是\(LCA\),输出即可,若要求路径关系,在\(dfs\)时顺便也预处理一下,数值,后面相同

int lca(int x,int y){
    if(d[x]<d[y])swap(x,y);
    for(int i=20;i>=0;i--){
        if(d[f[x][i]]<d[y])continue;
        x=f[x][i];
    }
    if(x==y)return x;
    for(int i=20;i>=0;i--){
        if(f[x][i]==f[y][i])continue;
        x=f[x][i];
        y=f[y][i];
    }
    return f[x][0];
}

注意:

1.\(dfs\)\(f_{i,0}\)就是其父节点
2.要给根节点的父节点和根节点深度赋值

完整代码:

#include<bits/stdc++.h>
using namespace std;
const int N=6e5+10;
vector<int>e[N];
int f[N][32],d[N];
void dfs(int u,int fa){
    d[u]=d[fa]+1;
    f[u][0]=fa;
    for(int i=1;(1<<i)<=d[u];i++)f[u][i]=f[f[u][i-1]][i-1];
    for(int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if(v==fa)continue;
        dfs(v,u);
    }
}
int lca(int x,int y){
    if(d[x]<d[y])swap(x,y);
    for(int i=20;i>=0;i--){
        if(d[f[x][i]]<d[y])continue;
        x=f[x][i];
    }
    if(x==y)return x;
    for(int i=20;i>=0;i--){
        if(f[x][i]==f[y][i])continue;
        x=f[x][i];
        y=f[y][i];
    }
    return f[x][0];
}
int main(){
    int n,m,s;
    cin>>n>>m>>s;
    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    d[s]=1;
    dfs(s,0);
    while(m--){
        int u,v;
        cin>>u>>v;
        cout<<lca(u,v)<<endl;
    }
}

练习:

\(1.Cheap Robot\) 题解
\(2.P4281 [AHOI2008]\) 紧急集合 / 聚会 题解
\(3.P5836 [USACO19DEC] Milk Visits S\) 题解

本文作者:XichenOC

本文链接:https://www.cnblogs.com/XichenOC/p/18682361

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   XichenOC  阅读(16)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起