倍增法lca

int dep[N],rt[25][N],siz[N];//rt数组需要在dfs之前置-1。

void dfs(int pos,int deep){
    dep[pos]=deep;
    siz[pos]=1;
    for(edge *it=adj[pos];it;it=it->next){
        if(!dep[it->id]){
            rt[0][it->id]=pos;
            dfs(it->id,deep+1);
            siz[pos]+=siz[it->id];
        }
    }
}

void prelca(){
    for(int i=1;i<=20;i++){
        for(int j=1;j<=n;j++){
            rt[i][j]=rt[i-1][j]==-1?-1:rt[i-1][rt[i-1][j]];
        }
    }
}

int LCA(int u,int v){//查询u和v的lca
    if(dep[u]<dep[v])swap(u,v);
    for(int i=0;i<21;i++){
        if((dep[u]-dep[v])>>i&1){
            u=rt[i][u];
        }
    }
    if(u==v)return u;
    for(int i=19;i>=0;i--){
        if(rt[i][u]!=rt[i][v]){
            u=rt[i][u];
            v=rt[i][v];
        }
    }
    return rt[0][u];
}

int jump(int pos,int num){//查询节点pos的第num个父亲
    for(int i=0;i<21;i++){
        if(num>>i&1){
            pos=rt[i][pos];
        }
    }
    return pos;
}
 
 
时间: 2024-10-13 11:50:16

倍增法lca的相关文章

Codeforces 519E A and B and Lecture Rooms [倍增法LCA]

题意: 给你一棵有n个节点的树,给你m次询问,查询给两个点,问树上有多少个点到这两个点的距离是相等的.树上所有边的边权是1. 思路: 很容易想到通过记录dep和找到lca来找到两个点之间的距离,然后分情况讨论. 一开始困扰我的问题是如果lca不是正中间的点,如何在比较低的复杂度的层面上求解中点. 倍增法lca不光可以在logn的时间复杂度内查询某两个点的lca,还可以实现在logm的时间复杂度能查询某个节点的第m个父亲节点. 算法的核心是用二进制的运算来实现查询. #include<bits/s

倍增法-lca codevs 1036 商务旅行

codevs 1036 商务旅行 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间.该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环. 你的任务是帮助该商人计算一下他的最短旅行时

poj1330Nearest Common Ancestors以及讲解倍增法求lca

Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20487   Accepted: 10784 Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below: In the figure, each node is labeled with an

倍增法求LCA

倍增法求LCA LCA(Least Common Ancestors)的意思是最近公共祖先,即在一棵树中,找出两节点最近的公共祖先. 倍增法是通过一个数组来实现直接找到一个节点的某个祖先,这样我们就可以在O(logn)的时间内求出求出任意节点的任意祖先. 然后先把两个节点中转化为深度相同的节点,然后一起向上递增,知道找到相同的节点,该节点就是这两个节点的最近公共祖先. 代码实现: 1 #include<cstdio> 2 #include<iostream> 3 #define N

(树形dp+LCA倍增法)CSU 1915 - John and his farm

题意: 有一个棵树,现在让你找两个点连接起来,这样必然成为一个环,现在要求这些环长度的期望,也就是平均值. 分析: 第一次做LCA题,做多校的时候,瞎几把找了模板敲,敲了个八九不离十,只是姿势不太好,需要考虑很多细节. 其实我觉得这题最多只能算中等题. 因为一直没空,写题解也晚了,已经有很多人写了题解,都写的不错.反正比我厉害. 这题用倍增法比较好一些,因为会用到关键点,也就是当v和u处在同一棵子树中时,找到更高点的下面那个点,倍增法通过深度跳跃可以很快找到.处理起来比其他两个LCA算法都方便.

HDU 5296 Annoying Problem 树链剖分 LCA 倍增法

HDU 5296 Annoying Problem 题目链接:hdu 5296 题意:在一棵给定的具有边权的树,一个节点的集合S(初始为空),给定Q个操作,每个操作增加或删除S中的一个点,每个操作之后输出使集合S中所有点联通的最小子树的边权和. 思路:最小子树上的节点的充要条件: 节点为(S集合中所有点的LCA)的子节点: 节点有一个子孙为S集合中的点. 那么我们给每个节点都开一个标记数组,初始为零,每加入一个节点,就把从这个节点到根节点路径上的点的值都+1,反之-1,这样通过对每个单节点值的查

用“倍增法”求最近公共祖先(LCA)

1.最近公共祖先:对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大.2.朴素算法:记录下每个节点的父亲,使节点u,v一步一步地向上找父亲,直到找到相同的“祖先”,即 是所求的答案,时间复杂度O(n).3.优化算法(倍增法):利用二进制的思想,想办法使一步一步向上搜变成以2^k地向上跳. 所以定义一个P[][]数组,使p[i][j]表示节点i的2^j倍祖先,因此p[i][0]即为i的父亲. 我们可以得到一个递推式p[i][j]=p

poj1470 LCA倍增法

倍增法模板题 #include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; #define maxn 1000 #define DEG 20 struct Edge{ int to,next; }edge[maxn*maxn*2]; int head[maxn],tot; void addedge(int u,int v){ edge[to

lca(最近公共祖先(在线)) 倍增法详解

转自大佬博客 : https://blog.csdn.net/lw277232240/article/details/72870644 描述:倍增法用于很多算法当中,通过字面意思来理解 LCA是啥呢  在一棵树当中 lca表示的是两个节点最近公共祖先, 大家看这课树哈节点5 ,3的lca就是1,13和11的LCA就是6.节点8,12的lca就是8,那么我们如何通过被增来实现LCA呢. 首先请大家认真看下面的分析. depth[x],表示x节点的深度. 大家看下这个数组 grand[x][i] ,