【图论】树上启发式合并

这篇具有很好参考价值的文章主要介绍了【图论】树上启发式合并。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本篇博客参考:

  • Oi Wiki 树上启发式合并
  • 算法学习笔记(86): 树上启发式合并

基本概念

首先,什么是 启发式合并

有人将其称为“优雅的暴力”,启发式合并就是在合并两个部分的时候,将内容少的部分合并至内容多的部分,减少合并的操作时间

树上启发式合并(dsu on tree) 可以被用来解决树上的 离线问题(请注意,必须要是离线问题,因为处理问题的顺序有讲究),特别是可以维护以每个点为根的子树中的信息

一般来说,对于查询以每个点为根的子树中的信息的问题,我们可以用树形dp来处理,但是如果每个点的信息不止一两个数字,而是很庞大的部分(比如说每个点所需要的信息都要多个map来存储),这样使用树形dp的空间复杂度将会非常庞大,而树上启发式合并可以用来解决这样的问题

代码实现

举个例子,比如说我们给出一棵树,树上的每个结点染色,现在我们需要统计以每个结点为根的子树中出现多少种颜色

最暴力的方法就是每个结点跑一次 dfs,用 cnt[] 数组存储每个颜色出现的次数,输出

但是很明显会T的很惨

树上启发式合并,图论,图论,深度优先,算法
这样的树中,我们首先计算2子树的信息,然后计算3子树的信息的时候我们又要把2子树清空,每计算一个新的子树都要把之前计算过的信息清空,根本存不下来信息啊

然后我们考虑一下怎么优化呢,父结点的信息和子结点相关,我们可以用子结点的信息更新父结点的信息,也就是,我们在计算1子树的所有结点信息时,假如4子树是234里最后一个被计算的,那我们算完4子树之后,可以不用清空 cnt 数组,反正我们计算1子树的时候还是要遍历4子树的,将4子树的信息全部保留,再加上前面23子树的信息就可以得到1子树的信息了

这个4子树应该怎么选择呢?换句话说,我们保留哪一个子树的信息不被删除呢?根据启发式合并的思想,保留最庞大的子树信息不动,就可以减少重复计算的次数了

在树链剖分时我们把树中结点最多的子树根结点叫做重子结点,也就是说,在树上启发式合并的过程中,我们需要先计算所有轻子结点的信息(每计算一个轻子结点之后都要删除这个结点对当前答案的影响),最后计算重子结点的信息(保留重子结点对当前答案的影响),然后再计算前面的轻子结点(这一次计算要保留结点对当前答案的影响)

用两遍 dfs 实现

下面是一些变量定义:文章来源地址https://www.toymoban.com/news/detail-852292.html

  • sz[u] 以 u 为根的子树的结点数量
  • son[u] 结点 u 的重子结点
  • col[u] 结点 u 的颜色
  • L[u] 结点 u 的 dfs 序
  • R[u] 以 u 为根的子树中结点 dfs 序的最大值
  • id[u] L 标号 u 对应的结点编号,有 id[L[u]] == u
  • cnt[u] 颜色 u 的出现次数
  • totcol 目前出现过的颜色个数
void dfs1(int u, int fa) // u: 当前结点  fa: 父结点
{
	L[u] = ++ totdfn; // 更新u的dfs序
	Node[totdfn] = u; // 更新dfs序的映射
	sz[u] = 1; // 初始化子树大小为1
	for (int i = 0; i < g[u].size(); i ++ )
	{
		int j = g[u][i]; // 子结点编号
		if (j == fa) continue;
		dfs1(j, u);
		sz[u] += sz[j]; // 用子结点的sz更新父结点的sz
		if (sz[j] > sz[son[u]]) son[u] = j; // 更新重子结点
	}
	R[u] = totdfn; // 更新当前子树中dfs序的最大值
}

void dfs2(int u, int fa, bool keep) // u: 当前结点  fa: 父结点  keep: 此次遍历计算的答案是否保留
{
	// 计算轻子结点的答案
	for (int i = 0; i < g[u].size(); i ++ )
	{
		int j = g[u][i]; // 子结点编号
		if (j == fa || j == son[u]) continue; // 遇到重子结点或者父结点就跳过
		dfs2(j, u, false); // 继续计算轻子结点的答案且不保留
	}

	if (son[u]) dfs2(son[u], u, true); // 计算重儿子答案并保留计算过程中的数据(用于继承)

	for (int i = 0; i < g[u].size(); i ++ )
	{
		int j = g[u][i]; // 子结点编号
		if (j == fa || j == son[u]) continue; // 遇到重子结点或者父结点就跳过

		// 子树结点的 DFS 序构成一段连续区间,可以直接遍历
		for (int k = L[j]; k <= R[j]; k ++ ) add(id[k]); // 加上轻子结点对答案的贡献
	}
	add(u); // 加上当前子树根结点对答案的贡献
	ans[u] = totcol;
	if (keep == false) // 如果当前计算的答案不保留 就删去
		for (int i = L[u]; i <= R[u]; i ++ ) del(id[i]);
}

到了这里,关于【图论】树上启发式合并的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 启发式搜索 :A*算法详解

    A*算法,(A-Star)算法是一种静态路网中求解 最短路径 最有效的 直接搜索方法 ,也是解决许多搜索问题的有效算法。 算法中的距离估算值与实际值 越接近 ,最终搜索速度越快。 对于求两个点之间的最短路 普通的BFS是按层遍历的过程,以起点为中心,以到终点的最短路为半径

    2023年04月08日
    浏览(30)
  • 【启发式算法】灰狼优化算法【附python实现代码】

    写在前面: 首先感谢兄弟们的订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 路虽远,行则将至;事虽难,做则必成。只要有愚公移山的志气、滴水穿石的毅力,脚踏实地,埋头苦干,积跬

    2024年02月16日
    浏览(23)
  • 非梯度类启发式搜索算法:Nelder Mead

    Hello,今天给大家介绍一种不基于梯度的优化算法 Nelder Mead。 Nelder Mead 算法通常是用来求解非线性(nonlinear)、导函数未知情况下目标函数的最大值或者最小值。学过梯度下降的同学应该知道,梯度下降类算法的每一步都需要计算当前位置的梯度,从而更新当前解使得最终逐

    2024年02月02日
    浏览(31)
  • 元启发式算法库 MEALPY 初体验-遗传算法为例

    官网: MealPY官网 开源许可: (GPL) V3 MEALPY (MEta-heuristic ALgorithms in PYthon) 是一个提供最新自然启发式元启发算法的Python模块,它是最大的此类Python模块之一。这些算法模仿自然界中的成功过程,包括生物系统以及物理和化学过程。mealPy 的目标是免费向所有人分享元启发领域的知识

    2024年04月11日
    浏览(32)
  • 启发式搜索算法:A算法(全局、局部择优算法)+A*算法 解决八数码问题

    参考博客:人工智能搜索策略:A*算法 在图搜索算法中,如果能在搜索的每一步都利用估价函数f(n)=g(n)+h(n)对Open表中的节点进行排序,则该搜索算法为 A算法 。由于估价函数中带有问题自身的启发性信息,因此,A算法又称为启发式搜索算法。 对启发式搜索算法,又可根据搜

    2024年02月10日
    浏览(27)
  • 人工大猩猩部队优化器:一种新的面向全局优化问题的自然启发元启发式算法(Matlab代码实现)

           目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨‍💻4 Matlab代码 元启发式在解决优化问题方面发挥着关键作用,其中大多数都受到自然界中自然生物集体智慧的启发。本文提出了一种新的元启发式算法,其灵感来自自然界大猩猩部队的社会智能,称为人工大猩猩部

    2024年02月01日
    浏览(30)
  • 数学启发式

    优化求解器 | Gurobi 数学启发式算法:参数类型与案例实现 数学启发式算法 | 可行性泵 (Feasibility Pump)算法精讲:一份让您满意的【理论介绍+编程实现+数值实验】学习笔记(Python+Gurobi实现) 大佬到底是大佬!这些资料太适合我这种没基础的人了! 数学启发式(Mathematical Heurist

    2024年02月04日
    浏览(25)
  • 【论文阅读】聚集多个启发式信号作为监督用于无监督作文自动评分

    本文提出一个新的无监督的AES方法ULRA,它不需要真实的作文分数标签进行训练; ULRA的核心思想是使用多个启发式的质量信号作为伪标准答案,然后通过学习这些质量信号的聚合来训练神经自动评分模型。 为了将这些不一致的质量信号聚合为一个统一的监督信号,我们将自动

    2024年02月16日
    浏览(27)
  • 如何进行测试分析与设计-HTSM启发式测试策略模型 | 京东云技术团队

    测试,没有分析与设计就失去了灵魂; 测试人员在编写用例之前,该如何进行测试分析与设计呢?上次在《测试的底层逻辑》中讲到了【输入输出测试模型】,还讲到了【2W+1H测试分析法】,但2W1H分析法是初步的分析方法,具体在测试中如何落地,还需要更细的设计。 今天

    2024年02月05日
    浏览(36)
  • Codeforces Round 890 (Div. 2) D. More Wrong(交互题 贪心/启发式 补写法)

    题目 t(t=100)组样例,长为n(n=2000)的序列 交互题,每次你可以询问一个区间[l,r]的逆序对数,代价是 要在的代价内问出最大元素的位置,输出其位置 思路来源 neal Codeforces Round 890 (Div. 2) supported by Constructor Institute D (交互+分治) 附加强 - 知乎 题解 赛中开题顺序大失败没看这个

    2024年02月14日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包