无重边有向连通图的强连通分量
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 #include<stack> 6 using namespace std; 7 int n,m,ntime;//ntime记录dfs访问时间 8 int instack[11000];//标记点是否在栈中 9 int dfn[11000];//节点在dfs过程中的访问序号(也可以叫做开始时间) 10 int low[11000];//从该节点出发dfs过程中该节点下方节点(开始时间大于该节点的开始时间,且由该节点可达的节点)所能到达的最早的节点的开始时间,初始low数组等于dfn数组 11 vector<vector<int> > g; 12 stack<int> st; 13 void tarjan(int u) 14 { 15 int i,v; 16 dfn[u]=low[u]=ntime++; 17 st.push(u); 18 instack[u]=1; 19 for(i=0;i<g[u].size();i++)//从u出发的每一条边 20 { 21 v=g[u][i]; 22 if(dfn[v]==0)//v还没被访问过 23 { 24 tarjan(v); 25 low[u]=min(low[u],low[v]); 26 } 27 else if(instack[v])//v在栈中 28 { 29 low[u]=min(low[u],dfn[v]); 30 } 31 } 32 if(dfn[u]==low[u])//u是一个强连通分量的根 33 { 34 do 35 { 36 v=st.top(); 37 st.pop(); 38 instack[v]=0; 39 printf("%d ",v);//输出属于这个强连通分量的所有的点的编号 40 }while(u!=v); 41 printf("\n"); 42 } 43 } 44 int main() 45 { 46 int i; 47 while(scanf("%d%d",&n,&m)!=EOF) 48 { 49 g.clear(); 50 g.resize(11000); 51 while(!st.empty()) st.pop(); 52 ntime=1; 53 memset(instack,0,sizeof(instack)); 54 memset(dfn,0,sizeof(dfn)); 55 memset(low,0,sizeof(low)); 56 int u,v; 57 for(i=0;i<m;i++)//点从1开始编号 58 { 59 scanf("%d%d",&u,&v); 60 g[u].push_back(v); 61 } 62 tarjan(1); 63 } 64 return 0; 65 }