首页 > 其他分享 >LCA学习笔记

LCA学习笔记

时间:2024-07-26 21:40:01浏览次数:5  
标签:int 笔记 textbf 学习 MAXN LCA 节点 size

LCA

\(\textbf{LCA=Lowest Common Ancestor}\)

即最近公共祖先

下文以 \(\textbf{LCA(a,b)表示节点a与节点b的最近公共祖先}\)

F1: 暴力算法

步骤:

(1)求出每个节点的深度(\(size\))

(2)询问两个点是否重合,若重合,则\(\textbf{LCA(a,b)=当前重合的节点}\)

(3)否则,选择 \(\textbf{max(size[a],size[b])}\) 并移动到他的父亲节点

F2:倍增写法

倍增写法是基于F1暴力写法的优化版本,改进了时间复杂度

步骤:

(1)定义倍增数组 \(LCA[MAXN][MAXNLOG]\) ,其中 \(LCA[i][j]\) 表示 \(i\) 节点向上减少 \(2^j\) 步可到达的节点

因为想要跳 \(2^j\) 步可以先网上跳 \(2^{j-1}\) 步然后再站在 \(2^{j-1}\) 的地方再跳 \(2^{j-1}\) 步

由上可得公式:

\(\textbf{LCA[i][j]}\) = \(\textbf{LCA[ LCA[i][j-1] ][ j-1 ]}\)

\(2^j\) = \(2^{j-1}\) + \(2^{j-1}\)

(2)把\(a,b\) 移动到同一深度,即\(\textbf{size[a]==size[b]}\)

设\(maxab=max(size[a],size[b])\) ,\(minab=min(size[a],size[b])\)

则我们将\(maxab\)向上跳\(\textbf{size[minab]-size[maxab]}\) 步

并将这个步数表示成二进制,即 \(2^n\) 步,其中

n=\(log_2^{size[minab]-size[maxab]}\)

由此即可通过 倍增数组 ( LCA[MAXN] [MAXLOG] ) 来向上跳 \(2^i\) 步

即可实现在时间复杂度为 \(O(log_2^n)\) 的情况下到达目标深度

(3)求出 \(LCA(a,b)\)

设 \(L\) 为 \(a\) 与 \(b\) 节点向上走的第 \(L\) 步后到达了同一节点,则此节点就是 \(LCA(a,b)\)

同理,节点 \(a\) 与 \(b\) 向上走的第 \(L-1\) 步肯定为不同的节点

反之,向上走的第 \(L+1\) 步就为节点 \(a\) 与节点 \(b\) 第二近公共祖先,次公共祖先

我们可以从大到小枚举往上走 \(2^i\) 步,若节点 \(a\) 与 \(b\) 为同一节点则停止,否则一起向上走,直到根节点

算法代码:

int size[MAXN],LCA[MAXN][MAXLOG];
int fi[MAXN];//节点的后代个数
int to[MAXN];//节点的具体每个儿子
int nxt[MAXN];//nxt[i]表示节点i最后一条连出去的边
void dfs(int a,int father)
{
    size[a]=size[father]+1;//子节点深度是父亲节点深度+1
    LCA[a][0]=fa;//a节点向上走2^0 步为其父亲节点
    for(int i=1;i<MAXLOG;i++)
    {
        LCA[a][i]=LCA[LCA[a][i-1]][i-1];//刚推的公式
    }
    for(int i=fi[a];i!=0;i=nxt[i])//类似于最短路中的链式向前星
    {
        if(to[i]!=father)
        {
            dfs(to[i],a);//递归调用
        }
    }
    return;
}
int getLCA(int x,int y)
{
    if(size[x]<size[y])//刚才我们是定义了maxab和minab,这里直接进行比较,选出深度较大的节点
    {
        swap(x,y);
	}
    for(int i=MAXLOG-1;i!=0;i--)
    {
        if(size[LCA[x][i]]>=size[y])
        {
            x=size[x][i];
	    }
	}
    if(x==y)
    {
        return x;//找到LCA了
	}
    for(int i=MAXLOG-1;i!=0;i--)
    {
        if(LCA[x][i]!=LCA[y][i])
        {
            x=LCA[x][i];
            y=LCA[y][i];
		}
	}
    return LCA[x][0];
}

F3:Tarjan 算法

步骤:

(1)使用 DFS 深搜整棵树,开始时每个节点都是一个独立的集合( 并查集

(2)DFS (x)时,每次访问完子树 y ,把集合 y 合并到 x

(3)当 x 的所有子节点都被访问结束后,标记 x 为 \(true\),即已被访问

(4)遍历所有关于 x 的询问 \((x,y)\) ,如果 y 已被访问,则本访问答案为并查集的\(find(y)\)

代码实现:

string g[MAXN],q[MAXN];
int f[MAXN];
bool book[MAXN];
void init()
{
    for(int i=1;i<=n;i++)
    {
        f[i]=i;
	}
    return;
}
int findfather(int x)
{
    if(x==f[x])
    {
        return x;
	}
    f[x]=findfather(x);
    return f[x];
}
void Union(int x,int y)//合并函数,将节点x所在的集合合并到集合y中
{
    f[findfather(x)]=f[findfather(y)];
    return;
}
void dfs(int x)
{
    for(int i=0;i<g[x].size();i++)
    {
        dfs(g[x][i]);
        Union(g[x][i],x);
    }
    book[x]=true;
    for(int i=0;i<q[x].size();i++)
    {
        int m=q[]
	}
    return;
}

标签:int,笔记,textbf,学习,MAXN,LCA,节点,size
From: https://www.cnblogs.com/Atserckcn/p/18326320

相关文章

  • 深度学习与图像识别(numpy2)
    获取numpy属性首先,我们通过Numpy中的一个方法arange(n),生成0到n-1的数组。np.arange(15)返回的结果是array([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14)  然后,再通过Numpy中的reshape(row,column)方法,自动构架一个多行多列的array对象。 a=np.arange(15).reshape(3,5)#代表3行......
  • 轻量级图像识别算法笔记(一)
    轻量级图像识别算法一、什么是轻量级图像识别算法?为什么要用轻量级图像识别算法?什么是轻量级图像识别算法?​轻量级识别算法是指那些设计和优化以在资源受限环境中高效运行的机器学习和深度学习算法。为什么要使用轻量级图像识别算法?设备限制:很多实际应用场景中,嵌入式......
  • 如何学习Doris:糙快猛的大数据之路(从入门到专家)
    引言:大数据世界的新玩家还记得我第一次听说"Doris"这个名字时的情景吗?那是在一个炎热的夏日午后,我正在办公室里为接下来的大数据项目发愁。作为一个刚刚跨行到大数据领域的新手,我感觉自己就像是被丢进了深海的小鱼—周围全是陌生的概念和技术。就在这时,我的导师拍了......
  • 学习Java的第十一天啦(2024.7.26)
    1.死锁的条件:死锁的产生还涉及到一些具体的条件,这些条件可以被看作是死锁产生的必要条件,包括:1.互斥条件:资源不能被多个进程或线程同时访问,即资源是互斥的。2.请求保持条件:进程或线程在请求资源时,已经持有其他资源,并且不愿意释放已经持有的资源。3.不可剥夺条件:已经分配给进......
  • 【小白记录深度学习】——物理信息神经网络(PINNs)
    本文的内容基于论文解读,解读的论文为Physics-InformedNeuralNetworksforShellStructures和RecentAdvancesandApplicationsofMachineLearninginExperimentalSolidMechanics:AReview什么是物理信息神经网络PINNs(Physics-informedNeuralNetworks,物理信息神......
  • 如何学习Presto:糙快猛的大数据之路(建立整体框架)
    这个系列文章用"粗快猛+大模型问答+讲故事"的创新学习方法,让你轻松理解复杂知识!涵盖Hadoop、Spark、MySQL、Flink等大数据所有热门技术栈,每篇万字长文。时间紧?只看开头20%就能有收获!精彩内容太多?收藏慢慢看!点击链接开启你的大数据学习之旅https://blog.csdn.net/u012955829......
  • JAVA集中学习第二周学习记录(四)
    系列文章目录第一章JAVA集中学习第一周学习记录(一)第二章JAVA集中学习第一周项目实践第三章JAVA集中学习第一周学习记录(二)第四章JAVA集中学习第一周课后习题第五章JAVA集中学习第二周学习记录(一)第六章JAVA集中学习第二周项目实践第七章JAVA集中学习第二......
  • JAVA集中学习第二周项目实践[图书管理系统]
    系列文章目录第一章JAVA集中学习第一周学习记录(一)第二章JAVA集中学习第一周项目实践第三章JAVA集中学习第一周学习记录(二)第四章JAVA集中学习第一周课后习题第五章JAVA集中学习第二周学习记录(一)第六章JAVA集中学习第二周项目实践文章目录系列文章目录......
  • 算法笔记|Day8字符串II
    算法笔记|Day8字符串II☆☆☆☆☆leetcode151.翻转字符串里的单词题目分析代码☆☆☆☆kamacoder55.右旋字符串(待补充)题目分析代码☆☆☆☆☆leetcode28.实现strStr()题目分析代码☆☆☆☆☆leetcode459.重复的子字符串题目分析代码☆☆☆☆☆leetcode151......
  • c语言学习之输入输出--getchar、scanf、printf
    1.输入输出功能  (1).C语言本身并不提供输入输出功能。  使用的是c语言函数库中的"标准输入输出"函数 (2).c语言函数库提供的输入输出函数   getchar、putchar:操作一个字符 'a'  gets、puts:操作一个字符串 如"abcd"   scanf、printf:格式化......