zoukankan      html  css  js  c++  java
  • [复习资料]一类简单的树上找最小连通块问题

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

    问题描述

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

    解决方法

    直接讲结论吧,首先 ( m dfs) 得出树上所有点的 ( m dfs) 序,不妨设将所有关键点按 ( m 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) 个点的树,边有边权,再给定若干个关键点,然后给最小的包含所有关键点的连通块的所有边的边权加一。

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

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

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

    和字符串算法的结合

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

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

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

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

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

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

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

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

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

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

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

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

    例题

    一些简单的字符串题目:

    洛谷P5840 [COCI2015]Divljak

    SP8093 JZPGYZ - Sevenk Love Oimaster

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

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

  • 相关阅读:
    PTA 乙级 1032 挖掘机技术哪家强 (20分) C++
    Jmeter接口测试之MD5函数使用
    charles基础理论一
    Jmeter接口测试之函数和cookies
    appium+robotframework之权限设置
    appium+robotframework之context问题解决
    jmeter接口测试之断言持续时间
    Appium+robotframework 自动化之软键盘的调起(文本框无法输入值)
    Jmeter接口测试之测试计划和线程组的关系
    Jmeter接口测试之用户定义变量
  • 原文地址:https://www.cnblogs.com/lsq147/p/14232473.html
Copyright © 2011-2022 走看看