• 【图论】割点和桥


    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的边唯一)。

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

  • 相关阅读:
    ACM成长之路
    洛谷P1047 校门外的树
    洛谷P1046 陶陶摘苹果
    2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 F题
    图论:POJ2186-Popular Cows (求强连通分量)
    DFS:POJ1562-Oil Deposits(求连通块个数)
    DFS:POJ3620-Avoid The Lakes(求最基本的联通块)
    map函数的应用:UVa156-Ananagrams
    set的应用:UVa10815-Andy's First Dictionary
    水题:UVa253-Cube painting
  • 原文地址:https://www.cnblogs.com/purinliang/p/14322233.html
Copyright © 2020-2023  润新知