无向图的连通性

割点

什么是割点

在无向图中所有能够互通的点构成了连通分量,其中有一些关键的点,如果删除它,如果这个联通分量被分成了两个或者更多,则称这个点为割点。

通俗的讲,现在有很多个主机连在一起构成网络,但是如果有一个主机烂掉了,你就无法访问洛谷,则称则称这个主机是一个割点。

求割点

在通过 DFS 遍历个图的时候,很容易发现如果一个点是割点,则它的儿子们都无法不通过还没被访问过的边返回割点之前的点,如下图所示:

piPsZhd.png

可以发现节点 2、3 都是割点,节点 2 的子节点们不能在不通过节点 2 的情况下到达节点一,节点 3 的子节点们只能通过 3 到达节点 1、2。

但是节点 4 不是割点,因为节点 5 可以直接跳过节点 4 到达节点 3。

知道了求割点的原理之后我们考虑算法实现,定义两个数组 $dfn[i]$ 和 $low[i]$。

$dfn[i]$ 表示第 $i$ 个节点第一次被访问到的顺序。

$low[i]$ 表示第 $i$ 个节点和 $i$ 的后代在不经过已经被访问过的边的条件下,能到达的 $dfn[]$ 最小的节点。

将刚刚的图从节点 1 开始遍历得到的结果如下:

piPsGNQ.png

节点 4、5 都能通过一条另外的边返回节点 3。

故我们就有了以下的代码:

vector<int> G[maxn];
int dfn[maxn], low[maxn];
bool iscut[maxn];
int cutsum = 0;
int root;

void dfs(int x) {
    dfn[x] = low[x] = dfn[0]++;
    int son = 0;
    for(auto to : G[x]) {
        if(!dfn[to]) {
            son++;
            dfs(to);
            low[x] = min(low[x], low[to]);                      //如果他的后代能到达,那它也可以 
            if(low[to] >= dfn[x] && x != root) cutsum += !iscut[x], iscut[x] = true; /这样子写可以方便去重 
        }
        else    //如果边已经被访问过了,回退处理                                               
            low[x] = min(low[x], dfn[to]);
    }
    if(son >= 2 && x == root) cutsum += !iscut[x], iscut[x] = true;
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇