圆方树 (Block-Cut Tree)
1. 核心定义与代数性质
圆方树是将无向图关于点双连通分量(v-BCC)进行结构分解所构建的等价树形结构。
- 点集划分:
- 圆点(Round Node):原图节点,编号范围
。 - 方点(Square Node):每个极大点双连通分量抽象出的代表节点,编号从
开始递增。 - 节点规模:若原图连通,方点数至多
,总节点数 。树相关数组必须严格开设 空间。
- 拓扑性质:
- 二分图结构:圆方树不存在圆-圆边或方-方边,仅存在圆-方边。
- 从属关系:方点连接其所在点双包含的所有圆点;圆点连接所有包含该圆点的方点。
- 割点与连通性判定:
- 原图割点充要条件:该点在圆方树中的度数
。 - 原图非割点充要条件:
(仅属于一个点双)。
- 路径等价定理:
- 必经点:原图
到 的所有简单路径的公共点集合(必经点),严格等价于圆方树上 树上简单路径上的所有圆点。 - 简单路径并:原图
到 所有简单路径经过的节点并集,严格等价于圆方树上 树上路径所经过的所有方点所管辖的圆点并集。
2. 构造算法 (Tarjan 点双维护栈)
在 Tarjan 求解点双的过程中,利用一个节点栈维护当前搜索子树中的节点。
核心状态转移与弹栈逻辑
- 访问节点
,记录时间戳 dfn[u] = low[u] = ++timer,并将入栈。 - 遍历邻接点
:
若
未访问:递归搜索 。回溯时更新 low[u] = min(low[u], low[v])。若满足判定条件
low[v] >= dfn[u]:触发新点双生成,创建方点
sq = ++tot。圆方树连边
。 循环弹出栈顶节点
并建立圆方树边 ,直至弹出 为止。 关键不变量:点
不得出栈,因割点可同时属于更高的点双。 若
已访问且不为直接树边反向边:更新 low[u] = min(low[u], dfn[v])。
3. 模板
cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 100005;
int n, m, tot;
vector<int> g[N]; // 原图邻接表
vector<int> adj[N * 2]; // 圆方树邻接表 (开 2N)
int dfn[N], low[N], timer;
int stk[N], top;
inline void add_tree_edge(int u, int v) {
adj[u].push_back(v);
adj[v].push_back(u);
}
void tarjan(int u) {
dfn[u] = low[u] = ++timer;
stk[++top] = u;
for (int v : g[u]) {
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
if (low[v] >= dfn[u]) {
int sq = ++tot;
add_tree_edge(u, sq);
do{
add_tree_edge(stk[top],sq);
}while(stk[top--]!=v);
}
} else {
low[u] = min(low[u], dfn[v]);
}
}
}
void build_bct() {
tot = n;
timer = top = 0;
for (int i = 1; i <= n; ++i) {
if (!dfn[i]) {
tarjan(i);
if (top > 0) --top; // 弹出孤立根节点
}
}
}4. 经典模型与解题范式
模型一:两点间路径割点 / 必经点查询
- 数学映射:求
的割点数量。 - 解法:
- 圆方树点权赋值:圆点权值设为
,方点权值设为 。 - 查询
路径权值和,剔除端点 自身(若端点不算割点):
- 复杂度:预处理倍增/树剖
,单次查询 或 (RMQ LCA)。
模型二:动态点权修改与路径最值
- 数学映射:支持单点修改原图点权,查询
任意简单路径上经过节点权值的最小值。 - 复杂度陷阱:若圆点连接多个方点(菊花图割点度数达
),修改单点若暴力更新所有相邻方点,单次退化至 。 - 优化策略:
- 定根圆方树(以 1 为根)。
- 每个方点用
std::multiset仅维护其子圆点的权值集合,不维护其父圆点。 - 单点修改:圆点
仅需从其父方点的 multiset中更新自身,修改代价严格。 - 路径查询:树链剖分查询线段树区间最小值。若
的 LCA 为方点,该方点未统计其父圆点的值,需额外将 加入最终结果取 。
模型三:三元组简单路径计数
数学映射:在无向图中统计有序三元组
的数量,使得存在一条简单路径依次经过 。 容斥赋权法:
对于固定的端点对
, 的可选数量等于 到 所有简单路径的点集并大小减 2。 根据圆方树路径性质,赋权规则:
圆点权值:
(割点在相邻两方点中被重复计算,通过 抵消重复贡献)。 方点权值:
(该点双内的点数,即该方点的度数 )。 任意两点
间的合法中继点数即为圆方树路径权值和。 树形 DP:统计每条树上路径经过的次数,转化为每个节点的贡献乘上经过该节点的路径条数,全图
线性完成。