tarjan模板(缩点,求有向图强连通分量)

来源:互联网 发布:邮箱的域名是什么 编辑:程序博客网 时间:2024/06/12 23:57


具体思路见详解网址:https://www.byvoid.com/blog/scc-tarjan;

然后整理出了这个tarjan模板,具体数组的功能代码都有注释。

const int N=100010;struct data{    int to,next;} tu[N*2];int head[N];int ip;int dfn[N], low[N];///dfn[]表示深搜的步数,low[u]表示u或u的子树能够追溯到的最早的栈中节点的次序号int sccno[N];///缩点数组,表示某个点对应的缩点值int step;int scc_cnt;///强连通分量个数void init(){    ip=0;    memset(head,-1,sizeof(head));}void add(int u,int v){    tu[ip].to=v,tu[ip].next=head[u],head[u]=ip++;}vector<int> scc[N];///得出来的缩点,scc[i]里面存i这个缩点具体缩了哪些点stack<int> S;void dfs(int u){    dfn[u] = low[u] = ++step;    S.push(u);    for (int i = head[u]; i !=-1; i=tu[i].next)    {        int v = tu[i].to;        if (!dfn[v])        {            dfs(v);            low[u] = min(low[u], low[v]);        }        else if (!sccno[v])            low[u] = min(low[u], dfn[v]);    }    if (low[u] == dfn[u])    {        scc_cnt += 1;        scc[scc_cnt].clear();        while(1)        {            int x = S.top();            S.pop();            if (sccno[x] != scc_cnt) scc[scc_cnt].push_back(x);            sccno[x] = scc_cnt;            if (x == u) break;        }    }}void tarjan(int n){    memset(sccno, 0, sizeof(sccno));    memset(dfn, 0, sizeof(dfn));    step = scc_cnt = 0;    for (int i = 1; i <=n; i++)        if (!dfn[i]) dfs(i);}


0 0