hihoCoder #1343 Stable Members

题目大意$ ewcommand{SD}{mathrm{SD}}$

给定一个 $n+1$ 个点的有向无环图,点从 $0$ 开始编号。无重边、自环,且从每个点 $u$ 都能到达 $0$ 号点。如果每条 $uleadsto 0$ 路径($u e 0$)都经过点 $v$ ($v e 0$ 且 $v e u$),则称 $u$ 不稳定,否则称 $u$ 稳定。求稳定点的个数。

一个错误解法

先记录我的一个错误做法。将输入的图中的边全部反向,从 $0$ 号点开始 DFS。有向无环图在 DFS 的过程中不会出现回边(backward edge,也译作「后向边」),只有树边、前向边(forward edge)和侧向边(cross edge,也译作「横叉边」)。点 $u$ 稳定等价于「存在两条点不相交的 $0leadsto u$ 路径」。而这个条件要是满足,那么必然出现连向 $u$ 的前向边或侧向边。在 DFS 的过程中,当发现有前向边或侧向边连向 $u$ 时,就检查当前这条 $0leadsto u$ 路径和之前找到的完全由树边构成 $0leadsto u$ 路径是否交叉,若无交叉,则 $u$ 稳定。可以通过类似 Tarjan 离线 LCA 算法的思路来判断上述两路径是否交叉,只要判断 $u$ 和 $0$ 是否在一个集合中(并查集),若在同一个集合中则无交叉。

代码:

#include <bits/stdc++.h>
#define rep(n) for(size_t __i = 0, __j=(n); __i < __j; ++__i)
#define rep2(i,n) for(size_t (i)=0, _i=n;(i)<_i;(i)++)
#define rep3(i,b,e) for(size_t i =(b); (i)<(e); (i)++)
#define ran(i,b,e) for(size_t (i)=(b); (i)<(e); (i)++)
#define drep2(i,n) for(size_t (i)=(n)-1; (i)>=0; (i)--)
using namespace std;
using ll=long long;
const size_t N=size_t(1e5+5);

vector<size_t> g[N];

bool is_stable[N];

size_t fa[N];

size_t root(size_t x){
    return x==fa[x]?x:fa[x]=root(fa[x]);
}
void unite(size_t x, size_t y){
    x=root(x);
    y=root(y);
    fa[x]=y;
}

bool vis[N];
void dfs(size_t u){
    vis[u]=true;
    for(auto v:g[u]) {
        if (!vis[v]){
            dfs(v);
            unite(v,u);
        }
        else if (root(v) == 0) is_stable[v] = true;
    }
}


int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    size_t n;
    cin>>n;
   ran(i,1,n){
       fa[i]=i; // init
       size_t k;
       cin>>k;
       rep(k){
           size_t x;
           cin>>x;
           g[x].push_back(i);
       }
   }
   dfs(0);
   for(auto x:g[0]) is_stable[x]=true;
   int ans=0;
   ran(i,1,n) ans+=is_stable[i];
   cout<<ans<<'
';
    return 0;
}

这个做法是错的,下面给出一个反例:

节点编号也是节点的访问顺序。这个做法将 $3$ 号节点判为不稳定的。

题解上的做法

这道题我没想出正解。


仍考虑输入的图。
如果每条 $uleadsto 0$ 路径($u e 0$)都经过 $v$ ($v e 0$ 且 $v e u$),则称 $v$ 是 $u$ 的支配点(dominator)。若 $v$ 是 $u$ 的支配点且 $v$ 是稳定的,则称 $v$ 为 $u$ 的稳定支配点(stable dominator)。
不难证明,支配点有下述性质:
性质 1

$u$ 的支配点可能不唯一,但一定分布在某条链上。

这个性质根据定义很容易证明。
性质 2

设 $v_1$、$v_2$ 是 $u$ 的两个支配点,那么或者 $v_1$ 是 $v_2$ 的支配点,或者 $v_2$ 是 $v_1$ 的支配点。

证明:
不失一般性,假设存在路径 $Pcolon uleadsto v_1leadsto v_2leadsto 0$ ,则必有 $v_2$ 是 $v_1$ 的支配点。若不然,即存在路径 $P'colon v_1leadsto 0$ 满足 $v_2$ 不在 $P'$ 上,从而 $v_2$ 也不是 $u$ 的支配点。

性质 3

若 $u$ 是不稳定的,则 $u$ 有唯一的稳定支配点。

证明:
用 $d(u)$ 表示 $u$ 到 $0$ 的最短距离。满足 $d(v)=1$ 的点 $v$ 必定是稳定的。
若 $v$ 是 $u$ 的支配点则必有 $d(v) < d(u)$ 。
由于 $u$ 的支配点的支配点也是 $u$ 的支配点,所以 $u$ 的稳定支配点必然存在。
$u$ 的稳定支配点是 $u$ 的所有支配点中距离 $0$ 号点最近的那个点。
又根据性质 $2$ 可知 $u$ 的稳定支配点唯一。

若 $u$ 不稳定,用 $SD(u)$ 表示 $u$ 的稳定支配点。

可以证明下述定理
定理 1

$u e 0$ 是稳定的当且仅当:
(1) 存在弧 $(u,0)$;或者
(2) 存在两条「点(除 $u$ 外)不相交」的路径 $uleadsto v_1$ 和 $uleadsto v_2$ 满足 $v_1$ 和 $v_2$ 都是稳定的。

必要性是显然的,条件(2)的充分性也很容易证明。


若图中存在 $uleadsto v$ 路径则称 $v$ 为 $u$ 的后继(successor),若图中存在弧 $(u,v)$ 则称 $v$ 为 $u$ 的直接后继(direct successor)。

具体实现就是:将图上的点拓扑排序,按照拓扑排序的逆顺序依次(根据定理 1)判断每个点是否稳定。定理 1 中的第二个条件中的 $v_1$、$v_2$ 包括:

  • $u$ 的稳定直接后继,
  • $SD(v)$:$v$ 是 $u$ 的不稳定直接后继。

下面证明
性质 4

设 $v_1$、$v_2$ 是 $u$ 的两个不稳定的直接后继。若 $SD(v_1) e SD(v_2)$,则存在两条点不相交的路径 $v_1leadsto SD(v_1)$ 和 $v_2leadsto SD(v_2)$ 。

证明:
反证法。
设 $P_1$ 是某一条 $v_1leadsto SD(v_1)$ 路径,令 $P_2$ 是任意一条 $v_2 leadsto SD(v_2)$ 路径,将路径 $P_1$、$P_2$ 上的交集记作 $V$($V e emptyset$),将 $V$ 中「拓扑序最小的点」和「拓扑序最大的点」分别记为 $s(V)$ 和 $t(V)$ 。由于 $SD(v_1)$ 是 $v_1$ 的支配点,可知 $SD(v_1)in V$,否则路径 $v_1 xrightarrow{P_1} s(V)xrightarrow{P_2} t(V) xrightarrow{P_2} SD(v_2)leadsto 0$ 是一条不经过 $SD(v_1)$ 的路径,这与 $SD(v_1)$ 是 $v_1$ 的支配点矛盾!故 $P_2$ 经过点 $SD(v_1)$ 。$P_2$ 是任意选取的,因而 $SD(v_1) e SD(v_2)$ 也是 $v_2$ 的稳定支配点,这又与性质 3 矛盾!所以假设不成立。

图中绿色路径表示 $P_1$,蓝色路径表示 $P_2$ 。

上述证明中有一个不严密的地方,即 $SD(v_2)leadsto 0$ 路径可能与 $P_1$ 相交;下面加以完善。
假设任意 $SD(v_2)leadsto 0$ 路径都与路径 $P_1$ 有交点;由于 $SD(v_2)$ 是稳定的,存在一条不经过点 $SD(v_1)$ 的 $SD(v_2)leadsto 0$ 路径 $P^*$,设 $w eSD(v_1)$ 是 $P_1$ 与 $P^*$ 的一个交点,则 $v_1xrightarrow{P_1} wxrightarrow{P^*} 0$ 也是一条不经过 $SD(v_1)$ 的路径,同样可导出矛盾。另外,容易证明,任意 $SD(v_2)leadsto 0$ 路径与 $P_2$ 都没有除 $SD(v_2)$ 以外的交点。

原文地址:https://www.cnblogs.com/Patt/p/7928969.html