首页 > 其他分享 >树链剖分lca笔记

树链剖分lca笔记

时间:2024-04-17 21:22:38浏览次数:27  
标签:剖分 int top 树链 lca 重链 节点

树链剖分求lca

参考资料:https://www.cnblogs.com/cangT-Tlan/p/8846408.html [树链剖分lca] 大佬讲的很清楚%%%orz

这篇博客是我的学习笔记。

树链剖分:树链剖分,计算机术语,指一种对树进行划分的算法,它先通过轻重边剖分将树分为多条链,保证每个点属于且只属于一条链,然后再通过数据结构(树状数组、BST、SPLAY、线段树等)来维护每一条链。(来自百度百科)

第一步是对树进行预处理,比如说处理每个节点的父节点,深度等等。

预处理的代码在下面:

int dfs(int now)
{
	siz[now] = 1;
	dep[now] = dep[fa[now]] + 1;
	for(int i = h[now]; i; i = e[i].nxt)
	{
		if(e[i].v != fa[now])
		{
			fa[e[i].v] = now;
			dfs(e[i].v);
			siz[now] += siz[e[i].v];
		}
	}
}

第二步就是找轻重链,其实我们只需要重链就可以了,下面是重边的概念:

在所有的儿子结点中,各以他们为祖先的子树的节点的个数多的儿子节点与其父亲的连边就是一条重边

感觉有点绕口,那么我们解释一下。

我们选中一个节点,以该节点为根节点,看看下一深度的子节点的子树的节点数量(感觉还是非常的绕口),选中子树节点数量最多的那个子节点,那么我们给这两个选中的节点之间的边染色,说明它是一条重边。相反地,轻边就是我们没有选中的边。(其实轻边没有什么用)

img

(从我看的那篇博客爬了个图过来)图中红色的边即为重边。9号节点的儿子的子树节点数量相同,随便选一个儿子染重边即可。

重边构成的链就是重链了。

树链剖分的代码在下面:

void tcp(int x)
{
	int t = 0;
	if(!top[x]) top[x] = x;//top[i]为沿着重链最高能走到哪个节点
	for(int i = h[x]; i; i = e[i].nxt)
	{
		if(e[i].v != fa[x] && siz[e[i].v] > siz[t]) t = e[i].v;
	}
	if(t)
	{
		top[t] = top[x];
		tcp(t); 
	}
	for(int i = h[x]; i; i = e[i].nxt)
	{
		if(e[i].v != fa[x] && t != e[i].v) tcp(e[i].v);
	}
} 

那么下面我们怎么使用树链剖分来求lca呢?????

先上代码:

int lca(int x, int y)
{
	while(top[x] != top[y])
	{
		if(dep[top[x]] < dep[top[y]]) swap(x, y);
		x = fa[top[x]];
	}
	if(dep[x] > dep[y]) swap(x, y);
	return x;
}

其实很好理解,当两个点位于一条重链上时停止操作。否则,重链顶端深度深的点,我们跳到这条重链的顶端的父节点(注意,不是重链的顶端,而是顶端的父节点),重复操作,在两个点位于一条重链上时,深度浅的点就是我们要找的lca。

(我又从那篇博客爬了一张图过来)

img

比如说,我们要找10,13节点的lca,我们观察到10号节点是个孤独的节点,那么我们跳到9号节点,随后13号节点跳到5号节点,我们发现5号节点和9号节点位于同一个重链上,那么深度较浅的5号节点就是10和13节点的lca。

标签:剖分,int,top,树链,lca,重链,节点
From: https://www.cnblogs.com/LikAzusa-Hina/p/18141801/LikAzusaaaaaaaaaaa

相关文章

  • 「树链剖分」 学习笔记
    一,树链剖分的思想与概述正如其名,树链剖分用于将树剖分成若干条链的形式,以维护树上路径的信息,其中剖分出的链有多种形式,最常见的是重链,还有长链或更多其它的链。其中剖分出的链为重链时,就引出了下文的主角「重链剖分」。重链剖分能保证划分出的每条重链上的节点DFS序连续,因此......
  • P4211 LCA 题解
    前置知识:树剖、差分题意给定一个\(n\)个节点的有根树树,根为\(1\)。有\(m\)个询问,每个询问给定\(l,r,z\),求\(\sum\limits_{i=l}^rdep[\textrm{LCA}(i,z)]\)。其中\(dep[x]\)表示\(x\)的深度,有\(dep[1]=1\)。题解式子中的\(dep\)不太好算,考虑转化成形式化......
  • [学习笔记] LCA - 图论
    [NOIP2013提高组]货车运输最大生成树+LCA+倍增好家伙,这道题我写了一个晚上,调了两个晚上,对于这道题我颇有感触。但这道题确实好,实实在在的蓝题,让我发现了许多关于LCA的问题。首先,这个题给的是一个无向图,并不是个树,为了减少运算量,我们可以把它变成一个树。运用Kruskal算法生......
  • 树链剖分 学习笔记
    随便写一点。1.原理定义重儿子为子树内子树大小最大的任一个点,重边为重儿子向其父亲连的边,其余为轻边。根据定义,轻边的父亲的子树大小一定不小于这个点的子树大小的二倍。又可以证出重边数量是\(O(\logn)\)的。因此可以用线段树维护这个东西。2.应用2.1dsu2.2lca考......
  • 【学习笔记】树链剖分
    一、重链剖分1.定义&作用树链剖分用于解决在树上执行的操作,将树上操作变为区间操作。用区间来维护。2.主要思想&实现有一棵树然后,我们把边区分一下,有一些边是“重边”,其余的是“轻边”,像这样:(红边为重边,黑边为轻)重边和轻边如何确定呢?看每一个结点旁的红色数字,代表他......
  • LCA 算法 : dfn 序
    洛谷题解区那个题解马蜂让我读到自闭,这篇文章,详细的讲一讲这个算法。一种基于预处理的快速LCA算法。预处理需要\(O(n\logn)\)查询,\(O(1)\),空间复杂度\(O(n\logn)\)。根据dfn序的性质,若\(u\)是\(v\)的祖先,那么$dfn_u<dfn_v$,因为先遍历节点再遍历子树,所以\(u\)......
  • 1039. 多边形三角剖分的最低得分
    题目链接:实现一、记忆化搜索classSolution{public:intminScoreTriangulation(vector<int>&values){intn=values.size();intmemo[n][n];memset(memo,-1,sizeofmemo);//-1表示还没有计算过function<int(int,int)>df......
  • 重链剖分学习笔记
    Part.1引入重链剖分是一种用于解决树上的路径查询和修改问题的算法,他能将\(O(n)\)级别的操作转换为\(O(\logn)\)的级别,可以说十分常用。本文将带你深入解析这个算法。Part.2概念和思路在讲解本算法之前,我们先引入一些概念:轻重儿子:对于一个树上的节点\(u\),其儿子中子......
  • 倍增(LCA与ST表)附详细讲解博客路劲以及洛谷模板题
    前置知识--倍增倍增算法,顾名思义,就是不断地翻倍。虽然是一种基础算法,但它能够使得线性的处理转化为对数级的处理,大大地优化时间复杂度,在很多算法中都有应用,其中最常见的就是ST表以及LCA(树上最近公共祖先)了。学习博客:算法学习笔记(12):ST表-知乎(zhihu.com)for(intx=......
  • LCA + 树上倍增
    LCA+树上倍增一、例题引入题目:2846.边权重均等查询现有一棵由n个节点组成的无向树,节点按从0到n-1编号。给你一个整数n和一个长度为n-1的二维整数数组edges,其中edges[i]=[ui,vi,wi]表示树中存在一条位于节点ui和节点vi之间、权重为wi的边。另......