zoukankan      html  css  js  c++  java
  • 有向图求强连通分量

    在图中找到一个最大的子图,使这个子图中每个两点都能够互相到达,这个最大的子图称为强连通分量,同时一个点也是属于强连通分量的。主要是通过dfs来实现的,在dfs的过程中维护了几个东西:一个stack用来存访问过的节点,就是靠栈来存的强连通分量的节点的,要一个dfn数组用于记录节点的时间戳,每个节点的dfn值是不会变的,还有最后一个是low数组,我的理解是对于low[i]来说,low[i]记录的是包含了i节点的强连通分量(也可以理解为强连通分量树)的根节点的dfn值,也可以理解为i通过i子树里的点能访问到的dfs树里最早的节点。

    1,2,3为一个scc,4为一个scc,5为一个scc

    int n,sccn,cnt,dfn[105],low[105],scc[105];//sccn记录scc个数,scc【i】记录i属于的scc
    vector<int>g[105];
    stack<int>sta;
    
    void dfs(int now){
        dfn[now]=low[now]=++cnt;
        sta.push(now);
        for(int i=0;i<(int)g[now].size();i++){
            int v=g[now][i];
            if(!dfn[v]){
                dfs(v);
                low[now]=min(low[now],low[v]);
            }else if(!scc[v]){
                low[now]=min(low[now],dfn[v]);
            }
        }
        if(low[now]==dfn[now]){//缩点操作,把图缩为sccn个点,要得到新图的话,枚举原来的边,然后如果两个点对应的scc不同则连边
            sccn++;
            for(;;){
                int tmp=sta.top();sta.pop();
                scc[tmp]=sccn;
                if(tmp==now) break;
            }
        }
    }

    推荐一篇入门博客https://blog.csdn.net/qq_34374664/article/details/77488976

  • 相关阅读:
    半同步/半反应堆线程池
    各种排序算法总结
    【面试题】求连续子数组的最大和(三种解法)
    数据结构查找、插入、删除时间复杂度
    红黑树
    opencv 图像基本操作
    plotroc.m
    roc.m
    perfcurve.m
    637. Average of Levels in Binary Tree
  • 原文地址:https://www.cnblogs.com/eason9906/p/11755014.html
Copyright © 2011-2022 走看看