1 #include<vector>
2 #include<cstring>
3 #define MAX_V 10050
4
5 int V,E; //V表示顶点数,E表示边数(顶点标号为0~V-1)
6 vector<int> G[MAX_V]; //图的邻接表表示
7 vector<int> rG[MAX_V]; //把边反向后的图
8 vector<int> vs; //后序遍历顺序的顶点列表(即用一个栈模拟了回溯时的标号)
9 bool used[MAX_V]; //DFS中用到的访问标记
10 int cmp[MAX_V]; //顶点所属强连通分量的拓扑序(0~k-1)
11
12 //向图中添加一条从_from到_to的边
13 void add_edge(int _from,int _to)
14 {
15 G[_from].push_back(_to);
16 rG[_to].push_back(_from);
17 }
18
19 //第一次在原图上的DFS
20 void dfs(int v)
21 {
22 used[v]=true;
23 for(int i=0;i<G[v].size();i++)
24 if(!used[G[v][i]])
25 dfs(G[v][i]);
26 vs.push_back(v);
27 }
28
29 //第二次在反向图上的DFS
30 void rdfs(int v,int k)
31 {
32 used[v]=true;
33 cmp[v]=k;
34 for(int i=0;i<rG[v].size();i++)
35 if(!used[rG[v][i]])
36 rdfs(rG[v][i],k);
37 }
38
39 //求解强连通分量(SCC:Strongly Connected Component),返回值为图中强连通分量的个数
40 int scc()
41 {
42 memset(used,false,sizeof(used));
43 vs.clear();
44 for(int v=0;v<V;v++)
45 if(!used[v])
46 dfs(v);
47
48 memset(used,false,sizeof(used));
49 int k=0;
50 for(int i=vs.size()-1;i>=0;i--)
51 if(!used[vs[i]])
52 {
53 rdfs(vs[i],k);
54 k++;
55 }
56
57 return k;
58 }