首页 > 其他分享 >树链剖分

树链剖分

时间:2024-05-02 17:34:38浏览次数:21  
标签:sz 剖分 int top son dfn 树链 root

树链剖分

我们一般使用重链剖分,就是子树大的先剖分,应为这样可以保证时间在 \(log_n\)
image
如图,先按照 \(dfs\) 序遍历出有一棵树,那么 \(dfs\) 序就是 \([1, 2, 3, 4, 5, 6, 7, 8, 9]\),如果碰到一条边上 \(dfn[f] - dfn[u] != 1\) 则断一次,就可以剖出链了,如图,链为 \([1, 2, 3] [4, 5] [6, 7, 8] [9]\),接下来我们还要维护两个东西,分别是 \(top_i\) 表示包含 \(i\) 的链的顶点,和 \(fa_i\) 表示 i 的父亲,代码:

void dfs1(int u, int f) {
	fa[u] = f;
	sz[u] = 1;
	for (auto v : g[u]) {
		if (v != f) {
			dfs1(v, u);
			sz[u] += sz[v];
			if (sz[son[u]] < sz[v]) son[u] = v;
		}
	}
}

void dfs2(int u, int f) {
	dfn[u] = ++dcnt;
	if (son[u]) {
		top[son[u]] = top[u];
		dfs2(son[u], u);
	} 
	for (auto v : g[u]) {
		if (v != son[u] && v != f) {
			top[v] = v;
			dfs2(v, u);
		}
	}
}

int main() {
	dfs1(root, 0);
	top[root] = root;
	dfs2(root, 0);
}

如果要找到 \(u\) 到根节点的路径可以参考以下代码:

int u = x;
while (top[u] != top[root]) {
	cout << u << " -> " << top[u] << " -> " << fa[top[u]];
	u = fa[top[u]];
}
cout << u << " -> " << v;

如果要找到 \(u\) 到 \(v\) 的 \(lca\) 可以参考如下代码:

int lca(int u, int v) {
	int ans = 0;
	while (top[u] != top[v]) {
		if (dfn[u] < dfn[v]) {
			swap(u, v);
		}
		u = fa[top[u]];
	}
	if (dfn[u] < dfn[v]) {
		return u;
	}
	return v;
}

标签:sz,剖分,int,top,son,dfn,树链,root
From: https://www.cnblogs.com/libohan/p/18170358

相关文章

  • 树链剖分
    树链剖分,简称树剖,就是把一颗又大又高的树拆成一些链,方便使用某些数据结构。一般树剖我们随便DFS一下,将整棵树分成一些链,其中里面的DFS序连续。链的数量不管怎样是固定的\(O(N)\)。hack:某种DFS序是\((1,3,2,5,4,7,6,9,8,11,10)\),只要你不走运刚好,就仍然可以把单次询......
  • 重链剖分题目选讲
    染色给定一棵\(n\)个节点的无根树,共有\(m\)个操作,操作分为两种:将节点\(a\)到节点\(b\)的路径上的所有点(包括\(a\)和\(b\))都染成颜色\(c\)。询问节点\(a\)到节点\(b\)的路径上的颜色段数量。颜色段的定义是极长的连续相同颜色被认为是一段。例如112221由......
  • 树链剖分
    link1link2前言:树链剖分实际上就是一种将树形结构剖分成一条条链状结构,并用线性数据结构来快速维护信息。重链剖分:一些定义:重儿子:一个节点的重儿子定义为它的子节点中子树节点最大的节点。轻儿子:一个节点除重儿子外的所有儿子重边:一个节点到它的重儿子的边即为重边......
  • 树链剖分
    参考链接:https://www.cnblogs.com/dx123/p/16320467.html(感谢董晓老师)树链剖分求LCA比倍增快一些https://www.luogu.com.cn/problem/P3379#include<bits/stdc++.h>constintN=5e5+5;usingnamespacestd;intn,m,root;inth[N],ne[2*N],e[2*N],idx;intdep[N]......
  • 树链剖分lca笔记
    树链剖分求lca参考资料:https://www.cnblogs.com/cangT-Tlan/p/8846408.html[树链剖分lca]大佬讲的很清楚%%%orz这篇博客是我的学习笔记。树链剖分:树链剖分,计算机术语,指一种对树进行划分的算法,它先通过轻重边剖分将树分为多条链,保证每个点属于且只属于一条链,然后再通过数据结......
  • 「树链剖分」 学习笔记
    一,树链剖分的思想与概述正如其名,树链剖分用于将树剖分成若干条链的形式,以维护树上路径的信息,其中剖分出的链有多种形式,最常见的是重链,还有长链或更多其它的链。其中剖分出的链为重链时,就引出了下文的主角「重链剖分」。重链剖分能保证划分出的每条重链上的节点DFS序连续,因此......
  • 树链剖分 学习笔记
    随便写一点。1.原理定义重儿子为子树内子树大小最大的任一个点,重边为重儿子向其父亲连的边,其余为轻边。根据定义,轻边的父亲的子树大小一定不小于这个点的子树大小的二倍。又可以证出重边数量是\(O(\logn)\)的。因此可以用线段树维护这个东西。2.应用2.1dsu2.2lca考......
  • 【学习笔记】树链剖分
    一、重链剖分1.定义&作用树链剖分用于解决在树上执行的操作,将树上操作变为区间操作。用区间来维护。2.主要思想&实现有一棵树然后,我们把边区分一下,有一些边是“重边”,其余的是“轻边”,像这样:(红边为重边,黑边为轻)重边和轻边如何确定呢?看每一个结点旁的红色数字,代表他......
  • 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\),其儿子中子......