• Tarjan算法求强连通图


    先把参考资料的传送门放一下:

    1、优质的B站视频讲解
    (里面老师给出了一个很不错的代码模板)

    2、tarjan求强连通分量+缩点+割点/割桥(点双/边双)以及一些证明(原理简述)


    先不论缩点是怎么做的,
    根据第一个B站视频里的模板,
    先用线性的邻接表维护有向图,
    基本实现一下Tarjan算法。

    const int maxn = 1e5 + 10;
    
    //线性邻接表维护有向图
    
    class Node{
    public:
        int nd,nxt;
        Node(){};
        Node(int nd_,int nxt_):nd(nd_),nxt(nxt_){};
    };
    
    Node G[maxn];
    int head[maxn];
    int cnt;
    
    void add(int u,int v){
        G[cnt] = Node(v,head[u]);
        head[u] = cnt++;
    }
    
    void init_G(){
        memset(head,-1,sizeof(head));
        cnt = 0;
    }
    
    //下面是Tarjan算法求强连通图
    int Low[maxn];
    int Dfn[maxn];
    int num = 0;//编号变量-赋值不能是0
    int out[maxn];//标记被栈弹出过的元素
    int Stack[maxn];//模拟栈
    int cur = 0;//cur应当始终指向Stack的尾端元素
    
    int ans = 0;
    
    /*我们假设结点的编号从1开始*/
    int dfs(int u){
        Low[u] = Dfn[u] = ++num;//结点编号
        Stack[++cur] = u;//结点入栈
        //下面开始遍历u的临界结点
        for(int i=head[u];~i;i=G[i].nxt){
            int v = G[i].nd;
            if(Dfn[v] == 0){//v没有被访问
                dfs(v);
                Low[u] = min(Low[u],Low[v]);
            }else if(!out[v]){//v已经被访问且还在栈中
                Low[u] = Low[v];//形成环
            }
        }
        //输出强连通分量
        if(Low[u] == Dfn[u]){
            int cur_num = 0;
            do{
                cur_num++;
                out[Stack[cur]]=1;
            }while(Stack[cur--] != u);
            //这里做的处理是为了统计点个数大于1的连通区块的总个数ans
            if(cur_num>1)ans++;
        }
        return 0;
    }
    
    int main(){
        frein("in.txt");
        int n,m;
        cin>>n>>m;
        init_G();
        for(int i=0;i<m;i++){
            int a,b;
            cin>>a>>b;
            add(a,b);
        }
        //由于图并不一定是弱连通图
        //所以这里对每一个没有访问过的结点都进行搜索
        //当然,一般这并不会让复杂度达到O(n*n)
        for(int i=1;i<=n;i++){
            if(!Dfn[i]){
                dfs(i);
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    

    OK

  • 相关阅读:
    模板template用法
    关联式容器MAP的用法----类似与python中的dict
    迭代器iterator
    c++中的vertor
    Git操作(git reset & get revert)
    代码度量标准
    __attribute__关键字
    Centos7.2部署.Net Core2.0 WebApi
    通过nginx 访问 centos 7 服务器上的.Net Core
    ASP.NET Core部署到CentOS7,使用Nginx代理
  • 原文地址:https://www.cnblogs.com/savennist/p/13887259.html
Copyright © 2020-2023  润新知