tarjan-强连通分量
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N=100010,M=1000010;
int ver[M],Next[M],head[N],dfn[N],low[N];
int stack[N],ins[N],c[N];
vector<int> scc[N];
int n,m,tot,num,top,cnt;
int hc[N],vc[N<<1],nc[N<<1],tc;
void add(int x,int y){
ver[++tot]=y,Next[tot]=head[x],head[x]=tot;
}
void add_c(int x,int y){//缩点
vc[++tc]=y,nc[tc]=hc[x],hc[x]=tc;
}
void tarjan(int x){
dfn[x]=low[x]=++num;
stack[++top]=x,ins[x]=1;
for(int i=head[x];i;i=Next[i])
if(!dfn[ver[i]]){
tarjan(ver[i]);
low[x]=min(low[x],low[ver[i]]);
}
else
if(ins[ver[i]]) low[x]=min(low[x],dfn[ver[i]]);
if(dfn[x]==low[x]){
cnt++;
int y;
do{
y=stack[top--],ins[y]=0;
c[y]=cnt,scc[cnt].push_back(y);
}while(x!=y);
}
}
//c[x]表示x所在强连通分量的编号
//scc[i]记录了编号为i的强连通分量中的所有节点
//图***有cnt个强连通分量
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int x=1;x<=n;x++)//缩点
for(int i=head[x];i;i=Next[i]){
int y=ver[i];
if(c[x]==c[y]) continue;
add_c(c[x],c[y]);
}
return 0;
}9 13 1 2 1 5 1 6 2 3 3 4 4 5 5 2 6 8 6 7 7 4 8 7 8 9 9 6

京公网安备 11010502036488号