割点和桥

割点和桥的概念都是在无向图中

给定无向连通图\(G\in(V,E)\)

若对于\(x\in V\),从图中删除节点\(x\)以及所有\(x\)链接的边后,\(G\)分裂成两个或两个以上个不相连的子图,则称\(x\)\(G\)割点

割点判定法则

\(x\)不是搜索树的根节点,则\(x\)是割点当且仅当搜索树上存在一个\(x\)的子节点\(y\)满足\(dfn[x]\le low[y]\).

特别的,若\(x\)是搜索树的根节点,则\(x\)是割点的条件当且仅当搜索树上存在至少两个子节点满足.

vector<vector<int>> e;

int cnt = 0;
vector<int> dfn, low;
vector<int> cut; // 储存所有的割点

void tarjan( int p , bool root = true ){
    int tot = 0;
    low[p] = dfn[p] = ++ cnt;
    for( auto q : e[p] ){
        if( !dfn[q] ){
            tarjan( q , false );
            low[p] = min( low[p] , low[q] );
            tot += ( low[q] >= dfn[p]); // 统计满足条件的子节点数
        }else low[p] = min( low[p] , dfn[q] );
    }
    if( tot > root ) cut.push_back(p);
    return ;
}

若对于\(e \in E\),从图中删除边\(e\)之后,\(G\)分裂成两个不相连的子图,则称\(e\)\(G\)割边

割边判定法则

无向边\((x,y)\)是桥,当且仅当搜索树上存在\(x\)的一个子节点\(y\),满足\(dfn[x]\le low[y]\).

桥一定是搜索树中的边,一个简单环中的边一定都不是桥。

vector<pii> bridges;
vector<vi> e;
vi dfn, low, fa;
int cnt;

void tarjan(int x) {
    low[x] = dfn[x] = ++cnt;
    for (auto y: e[x]) {
        if (!dfn[y]) {
            fa[y] = x, tarjan(y);
            low[x] = min(low[x], low[y]);
            if (low[y] > dfn[x])
                bridges.emplace_back(x, y);
        } else if (fa[x] != y)
            low[x] = min(low[x], dfn[y]);
    }
    return;
}
posted @ 2023-10-11 16:41  PHarr  阅读(34)  评论(0编辑  收藏  举报