有向图求强连通分量

在图中找到一个最大的子图,使这个子图中每个两点都能够互相到达,这个最大的子图称为强连通分量,同时一个点也是属于强连通分量的。主要是通过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

原文地址:https://www.cnblogs.com/eason9906/p/11755015.html