定义

对于一个有向图 $G$ 和起点 $s$,定义 $u$ 支配 $v$ 当且仅当所有从 $s$ 到 $v$ 的路径都经过点 $u$。支配树即所有支配关系构成的树。

不失一般性,在后文中都假设起点 $s$ 能到达图中的所有点。

DAG 上的做法

考虑按照拓扑序构建支配树。一开始树中仅有 $s$ 结点。

按照拓扑序,当处理点 $u$ 的时候,所有有边连向 $u$ 的点在支配树上的位置都已经确定。显然点 $u$ 在支配树上的父亲是那些点在支配树上的 $\operatorname{lca}$,直接倍增处理即可。

一般图上的做法

没有特殊说明,后文中结点的大小关系均指 $\operatorname{dfn}$ 的大小关系,一个结点的父亲/祖先均指这个点在 dfs 树上的父亲/祖先。

定义

如果对与点 $u,v$ 满足存在路径 $u\to v_1 \to \cdots \to v_k \to v$ 且 $\forall i \in [1,k], u_i > v$ ,那么我们称 $u$ 是 $v$ 的 半支配点

显然一个点的半支配点有多个,定义 $u$ 的 最小半支配点 为 $\operatorname{semi}(u)$

性质

1. $\operatorname{semi}(u)$ 一定是 $u$ 的祖先

证明:

显然点 $u$ 的自己满足存在路径的条件,因此 $\operatorname{semi}(u) \leq u$

那么考虑假设 $\operatorname{semi}(u)$ 不是 $u$ 的祖先。由于非树边一定从 $\operatorname{dfn}$ 大的连向 $\operatorname{dfn}$ 小的,所以 $(\operatorname{semi}(u),v_1)$ 这条边只能是树边。 如果 $(\operatorname{semi}(u),v_1)$ 是树边,那么根据 $\operatorname{semi}(u) < u < v$,可以推出 $u$ 在 $\operatorname{semi}(u)$ 的子树中,矛盾。

2. 删除原图非树边,加入形如 $(\operatorname{semi}(u), u)$ 的边,支配关系不变

证明:

形如 $(\operatorname{semi}(u), v)$ 的边在原图中对应一条路径,所以新图中不会引入新的路径,因此原图中的支配关系在新图中必然存在。

然后我们只需要证明对于新图中的支配关系 $(x,u)$ 一定在原图中存在。

新图中支配关系 $(x,u)$ 存在,当且仅当 $x$ 到 $u$ 路径上的任意点 $y$ 满足 $\operatorname{semi}(y) \geq x$。

而如果在原图中支配关系 $(x,u)$ 不存在,即在原图中存在一条不经过 $x$ 的路径 $s \to \cdots \to a \to b \to \cdots \to u(a < x < b)$,那么考虑 $b\to \cdots \to u$ 与 $x\to \cdots \to u$ 的第一个交点 $c$ ($c$ 可能等于 $u$), 应有 $\operatorname{semi}(c) \leq a$, 矛盾,所以新图中的支配关系都在原图中存在。

做法

先求出所有点的最小半支配点,然后删除非树边,加入形如 $(\operatorname{sami}(u), u)$ 的边,此时我们得到了一个与原图支配等价的 DAG,直接套用 DAG 上的做法即可(有更优秀的做法但我不会)。

接下来问题转化为如何求出所有的最小半支配点

考虑一条边 $u \to v$,根据大小关系分类讨论

  • $u < v$,那么 $u$ 是 $v$ 的半支配点
  • $u > v$,那么对于满足 $p > v$ 的 $u$ 的祖先 $p$,$p$ 的半支配点都是 $u$ 的半支配点

显然这覆盖到了所有半支配点的情况。

然后做法就比较显然了。按照 $\operatorname{dfn}$ 倒序枚举每一个点 $u$,考虑所有 $x\to u$ 的边,如果 $x < u$ 就用 $x$ 更新 $\operatorname{semi}(u)$,不然就用 $x$ 的所有满足 $p > u$ 的祖先 $p$ 的 $\operatorname{semi}(p)$ 更新 $\operatorname{semi}(u)$,用带权并查集优化即可。

实现

#include "https://gitee.com/coderoj/code/raw/master/creats/pipe.h"
constexpr int N = 300005;
constexpr int B = 20;
Vector<int> e[N], eb[N], ed[N], due[N];
int n, m;
int dfn[N], fa[N], semi[N], f[N][B], d[N], size[N], dfncnt=0;
void dfs(int u) {
 dfn[u] = dfncnt++;
 for (int v: e[u]) if (dfn[v] == -1) {
   fa[v] = u; dfs(v); } }
bool dfn_cmp(int u, int v) { return dfn[u] < dfn[v]; }
struct Dsu {
 int p[N], semi[N];
 Dsu() { 
   range(N)
   | ranges::foreach([&](int i) { p[i] = semi[i] = i; }); }
 int get(int u) { 
   if (u == p[u]) { return p[u]; }
   int pa = get(p[u]);
   semi[u] = std::min(semi[u], semi[p[u]], dfn_cmp); 
   return p[u] = pa; }
 void merge(int u, int v) { 
   u=get(u); v=get(v); p[v] = u; } 
} st;
int lca(int u, int v) {
 if (d[u] < d[v]) { std::swap(u,v); }
 int delta = d[u] - d[v]; for (int i=0;i<B;++i) if (delta & (1<<i)) { u=f[u][i]; }
 for (int i=B-1; i>=0; --i) if (f[u][i] != f[v][i]) { u=f[u][i]; v=f[v][i]; }
 return u==v ? u : f[u][0]; }
void init_f(int u, int ufa) {
 f[u][0] = ufa; d[u] = d[ufa] + 1;
 for (int i: range(B-1)) { f[u][i+1] = f[f[u][i]][i]; } }
void dfs1(int u) {
 size[u] = 1;
 for (int v: ed[u]) { 
   dfs1(v); size[u] += size[v]; } }
void preInit() { } void init() {
 n = sc.n(); m = sc.n();
 range(m)
 | ranges::foreach([](int){
   int u = sc.n(), v = sc.n();
   e[u].push_back(v); eb[v].push_back(u); });
} void solve() {
 memset(dfn, -1, sizeof(dfn)); dfs(1);
 for (int i: range(1, n+1)) { semi[i] = i; }
 Vector dfn_id = 
 Vector<int>(range(2,n+1)) 
 | ranges::sortby(dfn_cmp)
 | ranges::reverse;
 dfn_id
 | ranges::foreach([](int u) {
   eb[u] 
   | ranges::foreach([=](int x) {
     st.get(x); 
     semi[u] = std::min(semi[u], st.semi[x], dfn_cmp); 
     st.semi[u] = semi[u]; });
   due[dfn[u]] 
   | ranges::foreach([=](int x) { 
     st.merge(fa[x], x); });
   if (u != 1) { due[dfn[fa[u]]].push_back(u); } });
 std::move(dfn_id)
 | ranges::reverse
 | ranges::foreach([](int u) {
   int f = lca(fa[u], semi[u]);
   ed[f].push_back(u); init_f(u,f); });
 dfs1(1);
 std::cout << (
   Vector<int>(range(1,n+1)) 
   | ranges::transform([](int u) { return size[u]; })
 ) << std::endl;
}



Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.