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 }