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 }