zoukankan      html  css  js  c++  java
  • Tarjan求强连通分量、求桥和割点模板

    Tarjan 求强连通分量模板、参考博客

    #include<stdio.h>
    #include<stack>
    #include<algorithm>
    using namespace std;
    const int maxn = 1e3 + 10;
    const int maxm = 330000 + 10;
    struct EDGE{ int v, nxt; }Edge[maxm];
    int Head[maxn], cnt;
    int DFN[maxn], LOW[maxn], color[maxn], INDEX, id;
    bool vis[maxn];
    int N, M;
    stack<int> stk;
    
    inline void init()
    {
        while(!stk.empty()) stk.pop();
        for(int i=0; i<=N; i++)
            Head[i] = DFN[i] = LOW[i] = color[i] = -1,
        cnt = INDEX = id = 0;
    }
    
    inline void AddEdge(int from, int to)
    {
        Edge[cnt].v = to;
        Edge[cnt].nxt = Head[from];
        Head[from] = cnt++;
    }
    
    inline void tarjan(int u)
    {
        DFN[u] = LOW[u] = INDEX++;
        stk.push(u);
        vis[u] = true;
        for(int i=Head[u]; i!=-1; i=Edge[i].nxt){
            int Eiv = Edge[i].v;
            if(DFN[Eiv] == -1){
                tarjan(Eiv);
                LOW[u] = min(LOW[u], LOW[Eiv]);
            }else{
                if(vis[Eiv])
                    LOW[u] = min(LOW[u], LOW[Eiv]);
            }
        }
    
        if(DFN[u] == LOW[u]){
            color[u] = ++id;
            vis[u] = false;
            while(stk.top() != u){
                vis[stk.top()] = false;
                color[stk.top()] = id;
                stk.pop();
            }
            stk.pop();
        }
    }
    
    int main(void)
    {
        while(~scanf("%d %d", &N, &M)){
            init();
            int from, to;
            while(M--){
                scanf("%d %d", &from, &to);
                AddEdge(from, to);
            }
    
            for(int i=0; i<N; i++)
                if(DFN[i] == -1)
                    tarjan(i);
    
            printf("%d
    
    ", id);
        }
        return 0;
    }
    View Code

    Tarjan 求桥和割点模板

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e3 + 10;///图中顶点的数量
    const int maxm = 4e5 + 10;///图中边的数量
    struct EDGE{ int v, nxt; }Edge[maxm];
    int Head[maxn], cnt;///表头以及边的编号
    int LOW[maxn], DFN[maxn];///每个点最早可回溯到的祖先节点、每个点的遍历序号
    int Fa[maxn], INDEX;///Fa数组记录每一个点的父亲、INDEX是算法里的时间戳
    int N, M;
    
    inline void init()
    {
        for(int i=0; i<=N; i++)
            Head[i] = LOW[i] = DFN[i] = -1, Fa[i] = 0;
        cnt = INDEX = 0;
    }
    
    inline void AddEdge(int from, int to)
    {
        Edge[cnt].v = to;
        Edge[cnt].nxt = Head[from];
        Head[from] = cnt++;
    }
    
    void Tarjan(int v, int Father)
    {
        Fa[v] = Father;
        DFN[v] = LOW[v] = INDEX++;
        for(int i=Head[v]; i!=-1; i=Edge[i].nxt){
            int Eiv = Edge[i].v;
            if(DFN[Eiv] == -1){
                Tarjan(Eiv, v);
                LOW[v] = min(LOW[v], LOW[Eiv]);
            }
            else if(Father != Eiv)
                LOW[v] = min(LOW[v], DFN[Eiv]);
        }
    }
    
    ///这份代码中顶点编号是从 0 ~ N-1
    void Count()///统计割点和桥
    {
        Tarjan(0, -1);
    
        int Cut_Num = 0;///割点的数量
        int Root_Child  = 0;///根节点的儿子
        Tarjan(0, -1);
        for(int i=1; i<N; i++){
            int v = Fa[i];
            if(v == 0) Root_Child++;
            else if(LOW[i] >= DFN[v] && !is_cut[v])
                is_cut[v] = true, Cut_Num++;
        }
        if(Root_Child > 1)
            is_cut[0] = true, Cut_Num++;///根节点有超过一个儿子则说明也是割点
    
        for(int i=0; i<N; i++){
            int v = Fa[i];
            if(v >= 0 && LOW[i] > DFN[v]){
                // v->i is bridge
                //可以用一个 pair<int, int> 来记录
            }
        }
    }
    
    int main(void)
    {
        while(~scanf("%d %d", &N, &M)){
            init();
            int from, to;
            while(M--){
                scanf("%d %d", &from, &to);
                AddEdge(from, to);
                AddEdge(to, from);
            }
            Count();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    【乱侃】How do they look them ?
    【softeware】Messy code,some bug of Youdao notebook in EN win7
    【随谈】designing the login page of our project
    【web】Ad in security code, making good use of resource
    SQL数据库内存设置篇
    关系数据库的查询优化策略
    利用SQL未公开的存储过程实现分页
    sql语句总结
    sql中使用cmd命令注销登录用户
    SQLServer 分页存储过程
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/9608235.html
Copyright © 2011-2022 走看看