tarjan强联通分量(模板)
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<iostream> 5 #include<algorithm> 6 #define N 10000 7 using namespace std; 8 int x,y,n,m,t,tot,sum,top,time; 9 int head[N],col[N],stack[N],dfn[N],low[N],a[N][N]; 10 bool vis[N]; 11 struct Edge 12 { 13 int from,next,to; 14 }edge[N]; 15 int add(int x,int y) 16 { 17 tot++; 18 edge[tot].to=y; 19 edge[tot].next=head[x]; 20 head[x]=tot; 21 } 22 int read() 23 { 24 int x=0,f=1; char ch=getchar(); 25 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 26 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 27 return f*x; 28 } 29 int tarjan(int now) 30 { 31 //stack[]表示递归过程的栈,即用来判断该点是否已经加入到此次递归的栈中,在递归末尾,通过将vis置为false释放所有递归栈的元素 32 t=0; 33 dfn[now]=low[now]=++time;//初始每一个点的low值dfn等于它的时间戳 34 stack[++top]=now; vis[now]=true;//将该点入栈,标记为在栈中 35 for(int i=head[now];i;i=edge[i].next)//更新于他相连的点的low值 36 { 37 x=edge[i].to; 38 if(vis[x]) low[now]=min(dfn[x],low[now]);//如果该点已经在栈中,直接更新来到该点的那个点的low,不需要递归查询 39 else if(!dfn[x]) 40 { 41 tarjan(x); 42 low[now]=min(low[x],low[now]);//不在栈中,需要从该点继续递归拓展 43 } 44 } 45 if(low[now]==dfn[now])//说明以这个点结束强连通分量 46 { 47 sum++;// 强连通分量的个数加一 48 col[now]=sum;//将该点放在她所属的强连通分量了 49 for(;stack[top]!=now;top--) 50 { 51 col[stack[top]]=sum; 52 vis[stack[top]]=false; 53 } 54 vis[now]=false; 55 top--; 56 } 57 } 58 int main() 59 { 60 n=read(),m=read(); 61 for(int i=1;i<=m;i++) 62 { 63 x=read();y=read(); 64 add(x,y); 65 } 66 for(int i=1;i<=n;i++) 67 if(!dfn[i]) tarjan(i); 68 printf("%d",sum); 69 return 0; 70 }