【图论】割点和桥

struct CutvertexBridge {

    static const int MAXN = 2e5 + 10;
    static const int MAXM = 2e6 + 10;

    int n, m, t;

    struct Edge {
        int v, nxt;
    } e[MAXM * 2];
    int h[MAXN];

    int dfn[MAXN], low[MAXN];
    bool cut[MAXN], brg[MAXM];

    void Init(int n) {
        this->n = n, m = 1;
        for(int i = 1; i <= n; ++i)
            h[i] = 0;
    }

    void AddEdge(int u, int v) {
        if(u == v) {
            m += 2;
            return;
        }
        e[++m] = {v, h[u]}, h[u] = m;
        e[++m] = {u, h[v]}, h[v] = m;
    }

    void dfs1(int u, int root) {
        dfn[u] = low[u] = ++t;
        for(int i = h[u], cnt = 0; i; i = e[i].nxt) {
            int v = e[i].v;
            if(!dfn[v]) {
                dfs1(v, root);
                low[u] = min(low[u], low[v]);
                if(low[v] >= dfn[u]) {
                    if(u != root || ++cnt > 1)
                        cut[u] = 1;
                }
            } else
                low[u] = min(low[u], dfn[v]);
        }
    }

    void dfs2(int u, int from) {
        dfn[u] = low[u] = ++t;
        for(int i = h[u]; i; i = e[i].nxt) {
            int v = e[i].v;
            if(!dfn[v]) {
                dfs2(v, i ^ 1);
                low[u] = min(low[u], low[v]);
                if(low[v] > dfn[u])
                    brg[i / 2] = 1;
            } else if(i != from)
                low[u] = min(low[u], dfn[v]);
        }
    }

    void GetCutvertexs() {
        t = 0;
        for(int i = 1; i <= n; ++i)
            dfn[i] = low[i] = cut[i] = 0;
        for(int i = 1; i <= n; ++i) {
            if(!dfn[i])
                dfs1(i, i);
        }
    }

    void GetBridges() {
        t = 0;
        for(int i = 1; i <= n; ++i)
            dfn[i] = low[i] = 0;
        for(int i = 2; i <= m; i += 2)
            brg[i / 2] = 0;
        for(int i = 1; i <= n; ++i) {
            if(!dfn[i])
                dfs2(i, 0);
        }
    }

} cb;

验证链接:[洛谷P3388 割点] | [HDU4738 Caocao's Bridges]

割点和桥都和dfs搜索树非常相关,可以根据搜索树的树形dp做文章(统计子树大小之类),这个时候桥可能应该用点v表示(易知若(u,v)是桥,那么v到其搜索树的父节点u的边唯一)。

不存在割点的无向连通图叫“点双连通图”,不存在桥的无向连通图叫“边双连通图”

posted @ 2021-01-24 20:47  purinliang  阅读(125)  评论(0编辑  收藏  举报