ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[复习资料]一类简单的树上找最小连通块问题

2021-01-04 21:34:57  阅读:213  来源: 互联网

标签:连通 边权 复习资料 给定 dfs 字符串 rm 树上 关键点


目录

一类简单的树上找最小连通块问题

问题描述

给定一棵 \(n\) 个点的树,边有边权,再给定若干个关键点,求最小的包含所有关键点的连通块的边权和。

解决方法

直接讲结论吧,首先 \(\rm dfs\) 得出树上所有点的 \(\rm dfs\) 序,不妨设将所有关键点按 \(\rm dfs\) 序排序后得到的序列为 \(a_1,a_2,\dots,a_m\) ,那么答案就是 \((\operatorname{dist}(a_1,a_2)+\operatorname{dist}(a_2,a_3)+\cdots+\operatorname{dist}(a_{m-1},a_m)+\operatorname{dist}(a_{m},a_1))/2\) 。

为什么是这样的?考虑一条边的边权何时会被算入答案,当且仅当这条边的两边都存在关键点,如下图:

在计算路径的时候,我们从下往上计算了这条边的边权一次,从上往下又计算了一次,所以除以二就是答案。

如果这条边不应该被算入答案,那么显然就不会被算入答案。

其他扩展问题

一、给定一棵 \(n\) 个点的树,点有点权,再给定若干个关键点,求最小的包含所有关键点的连通块的点权和

解决方法:把点权上放到边权,然后唯一没有计算到的点权就是最上面的那个点的点权,直接加上去就行了。

二、给定一棵 \(n\) 个点的树,边有边权,再给定若干个关键点,然后给最小的包含所有关键点的连通块的所有边的边权加一。

解决方法:之前讲的是求和,这里变成了修改,其实都是一样的,通过上面按 \(\rm dfs\) 排序的处理之后,都转化成了路径求和和路径修改,如果是静态的可以树上差分做,如果是动态的差分后树状数组,树链剖分和 \(\rm LCT\) 都可以维护。

三、给定一棵 \(n\) 个点的树,边有边权,再给定一个关键点集合,需要实现加入删除点和求最小的包含所有关键点的连通块的边权和。

解决方法:使用一个 \(\rm set\) 维护这个关键点集合,然后每次插入一个点 \(w\) 就找到 \(\rm dfs\) 序小于该点的第一个点 \(u\) (如果没有就是 \(\rm dfs\) 序最大的点)和 \(\rm dfs\) 序大于该点的第一个点 \(v\) (如果没有就是 \(\rm dfs\) 序最小的点),然后相当于是去掉路径 \(u,v\) 的贡献,加上 \(u,w\) 和 \(w,v\) 的贡献。

和字符串算法的结合

其实我写这篇文章就是为了讲这个的。

考虑这样一个问题:给定若干模式串和若干匹配串,求每个模式串在所有匹配串中的出现次数。

显然可以使用 \(\rm AC\) 自动机来做,将模式串建立 \(\rm AC\) 自动机,然后把所有匹配串丢到自动机里面去跑,每到达一个节点就在 \(\rm fail\) 树上面进行根节点到当前点的链上加一操作,最后每个模式串对应节点的点权就是这个模式串的答案。

对于链上加操作,如果是静态的可以树上差分,如果是动态的可以用树链剖分或差分后树状数组线段树做。

换一个问题:给定若干模式串和若干匹配串,求每个模式串在多少个匹配串中出现过

如果仅有一个匹配串,可以求出 \(\rm AC\) 自动机上面对应的所有字符串的出现次数,如果次数大于 \(0\) 那么就表示这个字符串在模式串中出现过

如果有多个匹配串,显然不可以对每个模式串都进行一遍判断出现次数是否大于 \(0\) 的操作,因为做一次这样操作的复杂度是 \(\mathcal O(\text{AC自动机节点个数})\) 的,显然不太优美。

还有一种方法,就是每次走到新的一个节点,并不是直接链上加,而是一直往上找到没有被遍历过的点,然后再进行加和,实现过程如果使用二分加树剖的话,恐怕是 \(\mathcal O(\log_2^3n)\) 的,不推荐,如果是暴力跳 \(\rm fail\) 指针,复杂度可能就是假的了。

我们发现,最终出现在匹配串中的字符串,其实就是 \(\rm fail\) 树上所有遍历过的点到根的路径的,其实就是我们一开始讨论的问题,如果把这些遍历过的点和根节点看做是关键点,那么我们要实现的其实就是最小包含所有关键点连通块修改,于是就可以转化为路径修改。

这样做的复杂度是正确的,而且使用差分后时间复杂度就只带了一个 \(\log\) 。

再考虑另外一个问题:给定 \(n\) 个字符串和一个数集 \(S\) ,如果一个字符串仅在 \(n\) 个字符串中的 \(x\) 个字符串中出现过,并且 \(x\in S\) ,那么我们称这个字符串是“Imakf喜爱的”,请对于每个字符串它有多少个本质不同的子串是“Imakf喜爱的”。

由于是子串,所以我们先建立广义 \(\rm SAM\) ,接下来的问题就是求出 \(\rm SAM\) 上面每个节点对应字符串在哪些字符串里面出现过,和 \(\rm AC\) 自动机一样的,不过这次是在 \(\rm parent\) 树而不是 \(\rm fail\) 树上面实现连通块修改操作,然后处理完后再判断一下这个字符串是不是“Imakf喜爱的”,接下来的问题就是对于每个字符串找到其所有的“本质不同的子串”对应的节点,也就是连通块求和操作,码量可能有点大。

例题

一些简单的字符串题目:

洛谷P5840 [COCI2015]Divljak

SP8093 JZPGYZ - Sevenk Love Oimaster

洛谷P2336 [SCOI2012]喵星球上的点名

SAM 的题目好像没有找到呜呜呜,如果找了类似的题目可以在评论区提醒我一下,谢谢。

标签:连通,边权,复习资料,给定,dfs,字符串,rm,树上,关键点
来源: https://www.cnblogs.com/lsq147/p/14232473.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有