本slide是为了NJU集训队准备。。。。未完待续。。。
正经定义
: 无向图中的每条边至多位于一个简单环上,且任意两点可达。
由此可知仙人掌的构造方式很“优美”,即生成一棵树,把树的某些节点,都各自变成一个简单环,就变成了仙人掌。因此仙人掌大体围绕两个重点:树边
、简单环
。
圆方树不仅可以解决仙人掌图的问题,对于一般图,可以将一个点双用一个方点代替,进而用圆方树的思路解决。
入门篇
简单环判定
: codeforces 962F
题意:给出无向图,找到所有仅位于一个简单环上的边。
这里介绍仙人掌的基本姿势:tarjan求点双
原理:考虑仙人掌的两个组成元素:树边、简单环。我们重点要判断环是否是简单的,因此我们要想办法扔掉树边,而简单环同时也是点双(且为最特殊的点双,只有简单环的点双满足点数=边数的限制),而树边显然不存在点双中,因此判断依据为:仙人掌森林<=>每个点双中点数=边数
代码
仙人掌判定&简单计数
:Luogu P4129 [SHOI2006]仙人掌
题意:给出一个无向图,先判断是否为一棵仙人掌,然后求仙人掌的支撑子图个数。
支撑子图定义
:去掉一些边,但不改变原图连通性,这样的子图即为支撑子图。PS:生成树为极小支撑子图。
题解:1个仙人掌 <=> 连通性&点双均为简单环。
于是先dfs一次检验连通性,然后tarjan求点双,检验点双的点数=边数。
另外:本题需要使用高精度姿势
代码
进阶篇1:LCA在圆方树上的应用
预备姿势:圆方树 WC2017仙人掌课件
圆方树+LCA处理最小路径询问
:BZOJ 2125 最短路
题意:给出带边权仙人掌图,多次询问两点间最短路径。
树的情况
:一个LCA解决
非退化情况
:建立圆方树,LCA为圆点则正常求值,LCA为方点,环上部分需要走较短的弧。
代码&讲解
进阶篇2:普通树形DP在圆方树上的应用
预备姿势:圆方树 WC2017仙人掌课件
圆方树+DP求仙人掌直径
:BZOJ1023[SHOI2008]cactus仙人掌图
题意:给出一个仙人掌图,求其直径。
仙人掌直径
:Max(任意两点间的最短路径)
树的情况
:简单通过DP解决:每个点记录经过不同儿子到叶子的最大和次大路径长。
非退化情况
:对于圆点
而言,他真实存在于原图中,因此经过圆点的路径都可以用上述DP方式解决。对于方点
而言,由于方点代表一个环,那么经过方点意味着经过这个环,等价与求环基树的直径,使用经典的优先队列RMQ即可。
代码&详解
圆方树+DP求最大独立集
:BZOJ 4316 小C的独立集
题意:给出一棵仙人掌图,求最大独立集点数。
树的情况
:简单01DP。
非退化情况
:对于圆点
而言,采用树上相同的01DP。对于方点
,由于他代表一个环,我们可以通过dp[0/1]对环的根节点的贡献情况,推断出环的dp[0/1]的意义,即dp[0]表示不加任何限制情况下,除环的根节点之外的部分最大独立集点数;dp[1]表示不能选和 环的根节点 直接相连的两个点的情况下,除环的根节点之外的部分最大独立集点数,单独使用另外一个DP进行计算即可。
代码&详解
进阶篇3:树上经典算法&数据结构在圆方树上的应用
圆方树+树链剖分+线段树
:codeforces 487E Tourists
题意:给出一个连同的无向图,有点权。要求支持两种操作:查询x,y所有简单路径上的最小点权;修改某点点权。
x-y简单路径的并:用点双来缩点+圆方树处理成树。然后路径的并就是树上x-y的路径上的点所在点双的并。
于是让方点代表整个点双(除掉点双中dep最小的圆点,防止修改操作退化)的最小点权,并用可删除堆维护,再用链剖+线段树维护树链可以快速查询。
代码&详解