首页 > 其他分享 >LCA(倍增与Tarjan)

LCA(倍增与Tarjan)

时间:2024-05-28 21:23:47浏览次数:24  
标签:Tarjan int 代码 fa LCA 倍增

如果我来到了我们的 LCA,我是不是就可以假装偶遇你了


首先是倍增法,和 ST 表如出一辙呢。
注意 N 通常在 5e5 的范围

点击查看代码
int head[N], cnt;
struct Edge{
    int from, to, nxt;
}e[N << 1];
void add(int u, int v){
    e[++cnt].from = u;
    e[cnt].to = v;
    e[cnt].nxt = head[u];
    head[u] = cnt;
}

int fa[N][20], deep[N];
void dfs(int x, int father){
    deep[x] = deep[father] + 1;
    fa[x][0] = father;
    for(int i = 1; (1 << i) <= deep[x]; i++){
        fa[x][i] = fa[fa[x][i - 1]][i - 1];
    }
    for(int i = head[x]; i != 0; i = e[i].nxt){
        int v = e[i].to;
        if(v != father)
            dfs(v, x);
    }
}
int LCA(int x, int y){
    if(deep[x] < deep[y]) swap(x, y);
    for(int i = 19; i >= 0; i--)
        if(deep[x] - (1 << i) >= deep[y])
            x = fa[x][i];
    if(x == y) return x;
    // x 和 y 一起向上跳
    for(int i = 19; i >= 0; i--){
        if(fa[x][i] != fa[y][i]){
            x = fa[x][i];
            y = fa[y][i];
        }
    }
    return fa[x][0];
}


然后是 Tarjan 的算法,这里的代码将询问用链式前向星方式存储

点击查看代码
int fa[N], ans[N];
bool vis[N];
int head[N], cnt;
struct Edge{
    int from, to, nxt;
}e[N << 1];
void add(int u, int v){
    e[++cnt].from = u;
    e[cnt].to = v;
    e[cnt].nxt = head[u];
    head[u] = cnt;
}
int head_query[N], cnt_query;
struct Query{
    int from, to, num, nxt;
}q[N << 1];
void add_query(int u, int v, int num){
    q[++cnt_query].from = u;
    q[cnt_query].to = v;
    q[cnt_query].nxt = head_query[u];
    q[cnt_query].num = num;
    head_query[u] = cnt_query;
}

int find_set(int x){
    if(x != fa[x]) fa[x] = find_set(fa[x]);
    return fa[x];
}

void Tarjan(int x){
    vis[x] = true;
    for(int i = head[x]; i != 0; i = e[i].nxt){
        int v = e[i].to;
        if(!vis[v]){
            Tarjan(v);
            fa[v] = x;
        }
    }
    for(int i = head_query[x]; i != 0; i = q[i].nxt){
        int v = q[i].to;
        if(vis[v]){
            ans[q[i].num] = find_set(v);
        }
    }
}
真是太简洁了,一遍 dfs 遍历子树,一遍 遍历询问直接解出答案。

书上代码 find_set() 还不带路径压缩,但一定要路径压缩

标签:Tarjan,int,代码,fa,LCA,倍增
From: https://www.cnblogs.com/9102qyy/p/18218935

相关文章

  • SUPRA:无须额外训练,将Transformer变为高效RNN,推理速度倍增
    Transformers已经确立了自己作为首要模型架构的地位,特别是因为它们在各种任务中的出色表现。但是Transformers的内存密集型性质和随着词元数量的指数扩展推理成本带来了重大挑战。为了解决这些问题,论文“LinearizingLargeLanguageModels”引入了一种创新的方法,称为UPtraining......
  • Volcano社区新版本发布!7大功能全面增强队列能力与调度稳定性
    本文分享自华为云社区《Volcano社区v1.9.0版本正式发布!全面增强队列能力与调度稳定性》,作者:云容器大未来。北京时间2024年5月21日,Volcano社区v1.9.0版本正式发布,此次版本增加了以下新特性:支持弹性队列容量capacity调度支持队列与节点间的亲和调度Volcano支持Kubernet......
  • 基本技巧——倍增
    基本技巧——倍增概念倍增法,顾名思义就是翻倍、成倍增长。它能够使线性的处理转化为对数级的处理,大大地优化时间复杂度。常常在递推中状态空间的第二维记录二的整数次幂的值,通过这些值拼凑出答案。通过任意整数都可以表示为若干个二的次幂项的和(二进制),以此计算。ST表概述S......
  • FullCalendar插件js原生用法
    1.先看下要实现的效果图,左侧栏为当日时间,顶部为部门所有人员,表格内容是人员事件,要求数据多的时候,左侧栏和顶部固定,支持横竖滚动条,如图:  2.这里用的js原生写法:<html><head><title>工作记录详情</title><metaname="decorator"content="default"/><s......
  • LCA(最近公共祖先)
    LCA就是最近公共祖先,表示为\(\operatorname{lca}(a,b)\),它的求解方法主要有两种。倍增法这是最常用的一种可以动态求LCA的算法。时间复杂度为\(O(\log{n})\)。中心思想这个算法中有两个特殊的数组:\(depth[i]\)和\(fa[i][k]\)。\(depth[i]\):\(i\)点的深度,以\(root\)......
  • LCA[模板]
    #include<bits/stdc++.h>#defineintlonglong#defineMAXN500010usingnamespacestd;structedge{intnxt,to;};edgee[MAXN*2];inth[MAXN],ei;voidadd(intx,inty){ei++;e[ei].to=y;e[ei].nxt=h[x];h[x]=ei;}intu[......
  • fullcalendar-vue3插件实现时间资源图
    用的vue3+最新版本:官网链接:https://fullcalendar.io/demos效果如图:x轴为人员,y轴为当日的时间段:  1.安装引入npminstall--save@fullcalendar/core@fullcalendar/resource@fullcalendar/resource-timegrid package.json 2.附上代码<script>import{defin......
  • P4211 [LNOI2014] LCA
    题目大意给出一个\(n\)个节点的有根树。设\(dep[i]\)表示点\(i\)的深度,\(\operatorname{LCA}(i,j)\)表示\(i\)与\(j\)的最近公共祖先。有\(m\)次询问,每次询问给出\(l,r,z\),求\(\sum_{i=l}^rdep[\operatorname{LCA}(i,z)]\)。\(1\len,m\le50000\)。思......
  • 倍增专题
    倍增大专题[AHOI2008]紧急集合/聚会-洛谷题意:给定一棵树,多次查询费马点(bushi费马点的含义是:到三个点的距离之和最小Solution:考虑画图发现树上三点两两求lca,必然至少两个相同,然后我们只需要让费马点为另一个点就可以了,因为这一段路程只需要一个点走就最好了。//考虑到让......
  • LCA(最近公共祖先)应用
    LCA可以将一条树上路径拆成一或两半,所以我们可以将很多关于区间的算法拓展到树上。仓鼠找suger洛谷P3398考虑两条相交的纵向路径\([A,B]\)和\([C,D]\),如图:如果两条路径相交那么\(C\)是\(B\)的祖先,\(A\)是\(D\)的祖先,对于任意的路径\([A,X,B]\)和\([C,Y,D]\),如......