Tarjan模板

伪代码:

tarjan(u)
{
    dfn[u]=low[u]=++index;  //流水号
    Stack.push(u);
    for(从u可达的每一个点v)
    {
        if(v未被访问过)
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(v还在栈内)
            low[u]=min(low[u],dfn[v]); 
    }
    if(low[u]==dfn[u])
    {
        num_of_scc++;
        while(Stack.top()!=u)
        {
            记录信息
            st.pop(); 
        }
        记录信息
        st.pop(); 
    }
}

模板:

输入格式: 第一行:n,m,分别为点数和边数(n<=100000) 接下来m行,每行两个整数x,y,表示从x到y有一条有向边 (1<=x,y<=n)

输出格式: 一个整数表示强连通分量的数量

#include <bits/stdc++.h>
using namespace std;
const int MAXN=100005;
int n,m;
vector<int> G[MAXN];
int dfn[MAXN],low[MAXN],cnt=0,index_=0;
int scc[MAXN],size[MAXN];
bool inStack[MAXN];
stack<int> st;
void tarjan(int u)
{
    index_++;
    dfn[u]=index_;
    low[u]=index_;
    st.push(u);
    inStack[u]=true;
    for(int i=0;i<G[u].size();i++)
    {
        if(!dfn[G[u][i]])
        {
            tarjan(G[u][i]);
            low[u]=min(low[u],low[G[u][i]]);
        }
        else if(inStack[G[u][i]])
            low[u]=min(low[u],dfn[G[u][i]]);
    }
    if(low[u]==dfn[u])
    {
        cnt++;
        while(st.top()!=u)
        {
            scc[st.top()]=cnt;
            size[cnt]++;
            inStack[st.top()]=false;
            st.pop();
        }
        scc[st.top()]=cnt;
        size[cnt]++;
        inStack[st.top()]=false;
        st.pop();
    }
}
int main()
{
    ios::sync_with_stdio(0);   //syn加速
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        int x,y;
        cin>>x>>y;
        G[x].push_back(y);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            tarjan(i);
    cout<<cnt<<endl;
    return 0;
}

 

posted @ 2018-08-31 17:23  落笔映惆怅丶  阅读(155)  评论(0编辑  收藏  举报