Note -「圆方树」学习笔记
圆方树的定义
圆方树是由一个无向图转化出的树形结构。转化方法为:
- 所有原图的点为“圆点”。
- 对于每个点双连通分量:
- 删去点双内部“圆点”间的连边。
- 新建点双的代表点——“方点”。
- 方点向点双内的所有点连边。
举个例子:
观察图片,我们可以得到圆方树的一些性质:
- 不存在相邻的方点。
- 一个圆点同时隶属于它所邻接的所有方点所代表的点双。可见所有非叶子圆点都是原图的割点。
- 从圆点 \(u\) 到圆点 \(v\) 的树上路径所经过的圆点是原图 \(u\) 到 \(v\) 的所有路径一定经过的点。
圆方树的构造
既然跟点双相关,那肯定是 \(\text{Tarjan}\) 老爷爷上场啦!
圆方树的构造算法实质上就是在求点双的基础上构建一个新图。设当前结点为 \(u\),若发现其儿子(DFS 树上儿子)\(v\) 的 low[v]>=dfn[u]
,那么就知道 \(u\) 是一个割点或者是 DFS 树根。我们不必对此加以区分,直接将 \(u\) 和新建的方点 \(w\) 连边,然后 \(w\) 向所有退栈的点连边,圆方树就构造完成了。
实现
inline void Tarjan ( const int u, const int f ) {
dfn[u] = low[u] = ++ dfc, stk[++ tp] = u;
adj ( src, u, v ) if ( v ^ f ) { // 枚举原图上u的临界点,并保证其不是DFS树上u的父亲。
if ( ! dfn[v] ) {
Tarjan ( v, u ), chkmin ( low[u], low[v] );
if ( low[v] >= dfn[u] ) {
tre.add ( u, ++ snode ); // snode初值为n,用于计数新建结点。
do tre.add ( snode, stk[tp] ); while ( stk[tp --] ^ v );
// 向每个退栈的点连边。
}
} else chkmin ( low[u], dfn[v] );
}
}
细节
在运用圆方树的过程中,我们往往需要在方点维护一些信息。为了避免重复,我们一般在割点处单独维护圆点信息,而在方点中不考虑割点。(即在上文算法中,结点 \(snode\) 不考虑 \(u\) 的信息,只记录 \(v\) 的信息。)
圆方树的运用
「BZOJ 3331」压力
\(\mathcal{Description}\)
Link.
给定一个 \(n\) 个点 \(m\) 条边的连通无向图,并给出 \(q\) 个点对 \((u,v)\),令 \(u\) 到 \(v\) 的路径所必经的结点权值 \(+1\)。求最终每个结点的权值。
\(n\le10^5\),\(m,q\le2\times10^5\)。
\(\mathcal{Solution}\)
看到”必经之点“,应该考虑圆方树。
对于每个点对,直接在圆方树上作差分,最后一遍 DFS 求每个圆点的子树和即可。
详细题解:my solution。
「洛谷 P4320」道路相遇
\(\mathcal{Description}\)
Link.
给定一个 \(n\) 个点 \(m\) 条边的连通无向图,并给出 \(q\) 个点对 \((u,v)\),询问 \(u\) 到 \(v\) 的路径所必经的结点个数。
\(n,q\le5\times10^5\),\(q\le\min\{\frac{n(n-1)}2,10^6\}\)。
\(\mathcal{Solution}\)
和上一道几乎一样。预处理圆方树上每个点到根经过的圆点个数,然后求 LCA 计算答案。
详细题解:my solution。
「APIO 2018」「洛谷 P4630」铁人两项
\(\mathcal{Description}\)
Link.
给定一个 \(n\) 个点 \(m\) 条边的无向图(不保证联通),求有序三元点对 \((s,c,f)\) 的个数,满足 \(s,c,f\) 互不相同,且存在一条从 \(s\) 到 \(c\) 再到 \(f\) 的简单路径。
\(n\le10^5\),\(m\le2\times10^5\)。
\(\mathcal{Solution}\)
首先考虑这样一个问题,若 \(s,c,f\) 在同一点双中,是否一定满足条件。
答案是肯定的,这里不细说。
那么如果固定 \(s,f\),合法的 \(c\) 就可以在圆方树 \(s\) 到 \(f\) 路径上的所有圆点和所有方点所代表的圆点(除去 \(s,f\))。这是因为 \(c\) 取在任意点双内部,由我们的结论,都一定可以从某点进入点双,经过 \(c\),再从某点走出点双。
但简单的计算会导致重复——一个圆点对多个方点有贡献。
举个例子,对于 \(u-w-v\),\(w\) 是圆点,\(u,v\) 是方点,如果我们单纯地用点双大小作为方点的权值,\(w\) 就会在 \(u\) 和 \(v\) 中分别计算一次。
解决办法很巧妙:将圆点的权值设为 \(-1\)。考虑 \(s\) 到 \(f\) 的路径必然是”圆-方-圆-……-圆-方-圆“,两个端点的 \(-1\),去除了 \(s\) 和 \(f\) 的贡献,中间的 \(-1\) 去除了在左右的”方“中重复的贡献。那么,合法的 \(c\) 的数量就是 \(s\) 到 \(f\) 的树上路径权值之和。
于是,相当于求树上点对的路径权值和。反过来,固定 \(c\),维护子树信息求出 \((s,f)\) 的方案数,计算 \(c\) 的贡献即可。
详细题解:my solution(带上文所述性质的证明)。
「CF 487E」Tourists
\(\mathcal{Description}\)
Link.
维护一个 \(n\) 个点 \(m\) 条边的简单无向连通图,点有点权。\(q\) 次操作:
- 修改单点点权。
- 询问两点所有可能路径上点权的最小值。
\(n,m,q\le10^5\)。
\(\mathcal{Solution}\)
怎么可能维护图嘛,肯定是维护圆方树咯!
一个比较 naive 的想法是,每个方点维护其邻接圆点的最小值,树链剖分处理询问。
不过修改的复杂度会由于菊花退化:修改”花蕊“的圆点,四周 \(\mathcal O(n)\) 个方点的信息都需要修改。
联想到 array 这道题,我们尝试”弱化“方点所维护的信息。每个方点,维护其圆方树上儿子们的点权最小值。那么每次修改圆点,至多就只有其父亲需要修改信息了。
于是,每个方点用 std::multiset
或者常见的双堆 trick 维护最小值信息(推荐后者,常数较小),再用一样的树剖处理询问即可。
详细题解:my solution。
「SDOI 2018」「洛谷 P4606」战略游戏
\(\mathcal{Description}\)
Link.
给定一个 \(n\) 个点 \(m\) 条边的无向连通图,\(q\) 次询问,每次给出一个点集 \(s\),求至少在原图中删去多少个点,使得 \(s\) 中存在两点不连通。多组数据。
每组数据 \(n,q\le10^5\),\(m,\sum|s|\le2\times10^5\)。
\(\mathcal{Solution}\)
看到 \(\sum|s|\) 的限制,不难联想到虚树或者其它与 DFN 相关的算法。
所以,先建出圆方树,并处理好 DFN,LCA 的一系列信息。考虑到答案就是 \(s\) 中的点在树上构成的连通块中不在 \(s\) 集合里的圆点个数,可以求一个树上前缀和:\(sum_u\) 表示从 \(u\) 到根路径上的圆点个数。处理询问时,先将 \(s\) 按 DFN 从小到大排序,两两 LCA 计算贡献(\(s_1\) 和 \(s_{|s|}\) 也要算一次),最后除以 \(2\),得到 \(cnt\)。不过整个连通块的根(\(\operatorname{LCA}(s_1,s_{|s|})\))这个点的贡献被遗漏了,所以要再加上这个点单独的贡献。最终答案就是 \(cnt-|s|\)。
详细题解:my solution。
「BZOJ 4316」小C的独立集
\(\mathcal{Description}\)
Link.
求包含 \(n\) 个结点 \(m\) 条边的仙人掌的最大独立集。
\(n\le5\times10^4\),\(m\le6\times10^4\)。
\(\mathcal{Solution}\)
建出圆方树,考虑树上 DP。
设状态 \(f(i,0/1)\) 表示该点不选择/不限制选择与父亲相邻的圆点(对于圆点,即它本身)时,子树内的最大独立集。转移分圆点和方点讨论:
圆点:很显然,\(f(u,0)=\sum_{v\in son_u}f(v,1),f(u,1)=\max\{f(u,0),\sum_{v\in son_u}f(v,0)+1\}\)。
方点:考虑把环展开成链。在链上做一个子 DP,这里不赘述。
最后,\(f(root,1)\) 就是答案。
详细题解:my solution(含子 DP 详细说明)。
「洛谷 P5236」「模板」静态仙人掌
\(\mathcal{Description}\)
Link.
给定一个 \(n\) 个点 \(m\) 条边的仙人掌,\(q\) 组询问两点最短路。
\(n,q\le10^4\),\(m\le2\times10^4\)。
\(\mathcal{Solution}\)
提出一个环来考虑,从环上一点 \(u\) 到 \(v\),无非两条路径。可以按顺序处理一个前缀和,计算两条路径边权的最小值。这里不细说。
建圆方树(很多题解说建树的细节与普通图不一样,其实正常建也没有任何问题 qwq),发现一个圆点走进方点(点双),在走到父亲圆点的最短距离可以在 \(\text{Tarjan}\) 算法中预处理出来。考虑圆方树上的边权:圆点到父亲方点的边权为上述最短距离,否则为 \(0\)。对于询问 \((u,v)\),找到其 \(\text{LCA}\)(设为 \(w\)),分 \(w\) 的情况讨论:
- \(w\) 是圆点,那么 \(\text{LCA}\) 时求出的树上距离就是答案。
- \(w\) 是方点,此时树上距离实际上是 \(u\) 和 \(v\) 走到 \(w\) 的父亲圆点的距离之和,明显时错误的——\(u\) 和 \(v\) 走进同一个点双后,需要求一次最短距离而非直接在父亲会和。所以可以倍增求到 \(u\) 走进点双的第一个点(即方点向 \(u\) 点方向的儿子圆点)\(u'\),同理求出 \(v'\),利用处理的前缀和求到 \(u'\) 到 \(v'\) 的最短距离。那么答案就是 \(\operatorname{dist}(u,u')+\operatorname{dist}(u',v')+\operatorname{dist}(v',v)\)。
详细题解:my solution(含带图的环上前缀和讲解)。
「HNOI 2009」「洛谷 P4410」无归岛
\(\mathcal{Description}\)
Link.
原题的题目描述愣是没看懂 qwq。
给一个 \(n\) 个点 \(m\) 条边的仙人掌(或许有特殊性质,不过这里的解法不需要 www),点有点权,求带权最大独立集。
\(n\le10^5\),\(m\le2\times10^5\)。
\(\mathcal{Solution}\)
和上上题几乎一样,把圆点的 \(+1\) 改成 \(+\max\{0,a_u\}\) 就好。
我绝对不会告诉你我快读没判负数挂了三次 qwq。
详细题解:看上上题的吧,再水一篇太过分了 www。
Note -「圆方树」学习笔记的更多相关文章
- Note -「Dsu On Tree」学习笔记
前置芝士 树连剖分及其思想,以及优化时间复杂度的原理. 讲个笑话这个东西其实和 Dsu(并查集)没什么关系. 算法本身 Dsu On Tree,一下简称 DOT,常用于解决子树间的信息合并问题. 其实 ...
- 「快速傅里叶变换(FFT)」学习笔记
FFT即快速傅里叶变换,离散傅里叶变换及其逆变换的快速算法.在OI中用来优化多项式乘法. 本文主要目的是便于自己整理.复习 FFT的算法思路 已知两个多项式的系数表达式,要求其卷积的系数表达式. 先将 ...
- 仙人掌&圆方树学习笔记
仙人掌&圆方树学习笔记 1.仙人掌 圆方树用来干啥? --处理仙人掌的问题. 仙人掌是啥? (图片来自于\(BZOJ1023\)) --也就是任意一条边只会出现在一个环里面. 当然,如果你的图 ...
- 【学习笔记】圆方树(CF487E Tourists)
终于学了圆方树啦~\(≧▽≦)/~ 感谢y_immortal学长的博客和帮助 把他的博客挂在这里~ 点我传送到巨佬的博客QwQ! 首先我们来介绍一下圆方树能干什么呢qwq 1.将图上问题简化到树上问题 ...
- LOJ 2587 「APIO2018」铁人两项——圆方树
题目:https://loj.ac/problem/2587 先写了 47 分暴力. 对于 n<=50 的部分, n3 枚举三个点,把图的圆方树建出来,合法条件是 c 是 s -> f 路 ...
- 圆方树&广义圆方树[学习笔记]
仙人掌 圆方树是用来解决仙人掌图的问题的,那什么是仙人掌图呢? 如图,不存在边同时属于多个环的无向连通图是一棵仙人掌 圆方树 定义 原先的仙人掌图,通过一些奇妙的方法,可以转化为一棵由圆点,方点和树边 ...
- loj2587 「APIO2018」铁人两项[圆方树+树形DP]
主要卡在一个结论上..关于点双有一个常用结论,也经常作为在圆方树/简单路径上的良好性质,对于任意点双内互不相同的三点$s,c,t$,都存在简单路径$s\to c\to t$,证明不会.可以参见clz博 ...
- CF487E Tourists + 圆方树学习笔记(圆方树+树剖+线段树+multiset)
QWQ果然我已经什么都学不会的人了. 这个题目要求的是图上所有路径的点权和!QWQ(我只会树上啊!) 这个如果是好啊 这时候就需要 圆方树! 首先在介绍圆方树之前,我们先来一点简单的前置知识 首先,我 ...
- 【Java】「深入理解Java虚拟机」学习笔记(1) - Java语言发展趋势
0.前言 从这篇随笔开始记录Java虚拟机的内容,以前只是对Java的应用,聚焦的是业务,了解的只是语言层面,现在想深入学习一下. 对JVM的学习肯定不是看一遍书就能掌握的,在今后的学习和实践中如果有 ...
随机推荐
- 区别对待 .gz 文件 和 .tar.gz 文件
#检测 tar tvf xxx.tar.gz #解压 tar zxvf #检测 gunzip -tv yyy.gz #解压 gunzip yyy.gz
- VMware 创建的虚拟机,Xshell无法进行连接
使用场景: 在VMware 创建了Centos7后,Xshell一直连接不上,如果排查以下问题还是不行.就可以用这种方法了 1.配置了静态地址 2.VMware配置了NAT映射,划分了网段后 3.检查 ...
- Centos6.9虚拟机环境搭建
原文链接:https://www.toutiao.com/i6481534700216123918/ 一.准备工具 VMware Workstation CentOS-6.9-x86_64-minim ...
- CentOS6.5下安装Hadoop-2.7.3(图解教程)
注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6627365258090512909/ 已安装好虚拟机(3个节点) YUM源已安装好.系统版本CentOS6.5.j ...
- 《剑指offer》面试题56 - I. 数组中数字出现的次数
问题描述 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是O(n),空间复杂度是O(1). 示例 1: 输入:nums = [4,1 ...
- Solon Web 开发,一、开始
Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...
- luis使用手册
Luis聊天机器人的使用 首先打开luis官网 图5.1 luis官网界面 图5.2 app应用管理界面 界面显示现有应用,显示它们的名称,语言,日期,以及使用次数.点击创建一个新的app应用. ...
- 从容器镜像的选择-alpine 说起
在 容器崛起之前,Alpine 还是个无名之辈,可能是因为大家并不是很关心操作系统本身的大小,毕竟大家只关心业务数据和文档,程序.库文件和系统本身的大小通常可以忽略不计. 容器技术席卷整个软件产业之后 ...
- gin中绑定表单数据至自定义结构体
package main import "github.com/gin-gonic/gin" type StructA struct { FieldA string `form:& ...
- lambda表达式的学习
Lambda表达式 为什么使用lambda表达式 Lambda表达式可以简化我们的代码,使我们只需要关注主要的代码就可以. //测试用的实体类 public class Employee { priv ...