您的位置:首页 > 其它

【模板】【强连通分量】【Tarjan】

2018-04-01 13:15 344 查看
题目索引:http://oi.nks.edu.cn/zh/Problem/Details/1121#include <cmath>
#include <stack>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define DB double
#define SG string
#define LL long long
#define Map(A,B) Map[A][B]
#define Fp(A,B,C,D) for(A=B;A<=C;A+=D)
#define Fm(A,B,C,D) for(A=B;A>=C;A-=D)
#define Clear(A) memset(A,0,sizeof(A))
using namespace std;
const LL Max=1e6+5;
const LL Mod=1e9+7;
const LL Inf=1e18;
stack<LL>S;
LL N,Num,Scc,Ans,In[Max],Dfn[Max],Low[Max],Bel[Max];
LL Cnt,To[Max<<1],Next[Max<<1],Head[Max];
inline LL Read(){
    LL X=0;char CH=getchar();bool F=0;
    while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
    while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
    return F?-X:X;
}
inline void Write(LL X){
    if(X<0)X=-X,putchar('-');
    if(X>9)Write(X/10);
    putchar(X%10+48);
}
void Insert(LL X,LL Y){
    To[++Cnt]=Y;Next[Cnt]=Head[X];Head[X]=Cnt;
}
void Tarjan(LL X){
    LL I,J,K,Y;
    Dfn[X]=Low[X]=++Num;
    S.push(X);
    for(I=Head[X];I;I=Next[I]){
        Y=To[I];
        if(!Dfn[Y]){
            Tarjan(Y);
            Low[X]=min(Low[X],Low[Y]);
        } else if(!Bel[Y]){
            Low[X]=min(Low[X],Dfn[Y]);
        }
    }
    if(Dfn[X]==Low[X]){
        ++Scc;
        Y=S.top();S.pop();Bel[Y]=Scc;
        while(X!=Y){
            Y=S.top();S.pop();Bel[Y]=Scc;
        }
    }
}
int main(){
    LL I,J,K;
    N=Read();
    Fp(I,1,N,1){
        Fp(J,1,N,1){
            K=Read();
            if(K==1){
                Insert(I,J);
            }
        }
    }
    Fp(I,1,N,1){
        if(!Bel[I]){
            Tarjan(I);
        }
    }
    Fp(I,1,N,1){
        for(J=Head[I];J;J=Next[J]){
            LL Y=To[J];
            if(Bel[I]!=Bel[Y]){
                In[Bel[Y]]=1;
            }
        }
    }
    Fp(I,1,Scc,1){
        if(!In[I]){
            Ans++;
        }
    }Write(Ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: