1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m; 4 struct edge{ 5 int next,to; 6 }e[1000]; 7 int tot; 8 int first[10009]; 9 int dfn[10009]; 10 int low[10009]; 11 int ans; 12 int sum; 13 int sta[10009]; 14 bool insta[10009]; 15 int top;//表示栈顶位置 16 int id[100009];//标记是哪一组的 17 void add_edge(int a,int b) 18 { 19 tot++; 20 e[tot].next=first[a]; 21 first[a]=tot; 22 e[tot].to=b; 23 } 24 void dfs(int now) 25 { 26 sum++; 27 low[now]=sum,dfn[now]=sum; 28 top++; 29 sta[top]=now,insta[now]=true; 30 for(int i=first[now];i;i=e[i].next) 31 { 32 if(dfn[e[i].to]==0) 33 { 34 dfs(e[i].to); 35 if(low[e[i].to]<low[now]) 36 { 37 low[now]=low[e[i].to]; 38 } 39 } 40 else 41 { 42 if(insta[e[i].to]==true&&dfn[e[i].to]<low[now]) 43 { 44 low[now]=dfn[e[i].to]; 45 } 46 } 47 } 48 if(low[now]==dfn[now]) 49 { 50 ans++; 51 int p=sta[top]; 52 while(p>now) 53 { 54 id[p]=ans; 55 insta[p]=false; 56 top--; 57 p=sta[top]; 58 } 59 top--; 60 id[now]=ans; 61 insta[now]=false; 62 } 63 } 64 int main() 65 { 66 cin>>n>>m; 67 for(int i=1;i<=m;i++) 68 { 69 int a,b; 70 cin>>a>>b; 71 add_edge(a,b); 72 } 73 for(int i=1;i<=n;i++) 74 { 75 if(dfn[i]==0)dfs(i); 76 } 77 cout<<ans<<endl; 78 for(int i=1;i<=n;i++) 79 { 80 printf("%d属于第%d个强连通分量\n",i,id[i]); 81 } 82 }
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 8 const int maxn = 10001; 9 const int maxm = 10001; 10 int first[maxn],id[maxn]; //id[i]表示:i点所属强连通分量的编号 11 int next[maxm],en[maxm]; 12 int dfn[maxn],low[maxn],sta[maxn]; 13 bool insta[maxn]; 14 int tot=0,sign=0,top=0,n,m,a,b,sum=0,i; 15 16 void Add(int x, int y) 17 { 18 tot++; 19 next[tot]=first[x]; 20 first[x]=tot; 21 en[tot]=y; 22 } 23 24 void dfs(int x) 25 { 26 int k,i; 27 sign++; 28 low[x]=sign; dfn[x]=sign; //x根的时间戳,x的时间戳 29 top++; 30 sta[top]=x; insta[x]=true; //sta[top]表示栈顶;insta[x]=true 是x在栈中的标记 31 k=first[x]; //枚举从x出发的第一条边 32 while(k!=0) //枚举从x出发的所有边 33 { 34 i=en[k]; //对面顶点 35 if(dfn[i]==0) //时间戳为0,没有搜索过 36 { 37 dfs(i); //从i出发继续搜索 38 if(low[i]<low[x]) low[x]=low[i]; //更新x的根的时间戳(缩小) 39 } 40 else //如果i搜索过 41 { 42 if((insta[i]) && (dfn[i]<low[x])) low[x]=dfn[i]; //如果i还在栈中,更新x的根的时间戳(缩小) 43 } 44 k=next[k]; //从x出发的下一条边 45 } 46 if(low[x]==dfn[x]) //如果从x出发的所有边都枚举了,并且x根的时间戳就是自己的时间戳,说明x是一个强连通分量的根 47 { 48 sum++; //累加强连通分量数量 49 i=sta[top]; //得到栈顶的顶点编号 50 while(i!=x) //依次出栈 51 { 52 id[i]=sum; //得到i点所属强连通分量 53 insta[i]=false; //出栈标记 54 top--; 55 i=sta[top]; //新的栈顶位置 56 } 57 top--; //x出栈 58 id[x]=sum; //得到x点所属强连通分量 59 insta[x]=false; //出栈标记 60 } 61 } 62 63 int main() 64 { 65 freopen("tarjan.in","r",stdin); 66 freopen("tarjan.out","w",stdout); 67 cin>>n>>m; 68 for(i=1;i<=m;i++) 69 { 70 cin>>a>>b; 71 Add(a,b); 72 } 73 74 memset(dfn,0,sizeof(dfn)); 75 sum=0; sign=0; 76 for(i=1;i<=n;i++) 77 if(dfn[i]==0) dfs(i); 78 79 cout<<sum<<endl; //输出强联通的个数 80 for(i=1;i<=n;i++) 81 cout<<i<<" 属于第 "<<id[i]<<" 个强连通分量"<<endl; 82 return 0; 83 }
原文:https://www.cnblogs.com/1129-tangqiyuan/p/11460343.html