procedure Strongly_Connected_Components(G);
- begin
- 1.深度优先遍历G,算出每个结点u的结束时间f[u],起点如何选择无所谓。
- 2.深度优先遍历G的转置图GT,选择遍历的起点时,按照结点的结束时间从大到小进行。遍历的过程中,一边遍历,一边给结点做分类标记,每找到一个新的起点,分类标记值就加1。
- 3. 第2步中产生的标记值相同的结点构成深度优先森林中的一棵树,也即一个强连通分量
- end;
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=10000+10;
bool vis[maxn];
int ID[maxn]; //点的颜色编号
int ncolor;
vector<int> s;
vector<vector<int> > color(maxn); //同一种颜色的点
vector<vector<int> > G(maxn);
vector<vector<int> > GT(maxn);
void dfs(int u){
vis[u]=true;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(!vis[v]) dfs(v);
}
s.push_back(u);
}
void dfs2(int u){
vis[u]=true;
ID[u]=ncolor;
color[ncolor].push_back(u);
for(int i=0;i<GT[u].size();i++){
int v=GT[u][i];
if(!vis[v]) dfs2(v);
}
}
void Korasaju(int n)
{
memset(vis,false,sizeof(vis));
s.clear();
for(int i=1;i<=n;i++) if(!vis[i]) dfs(i);
memset(vis,false,sizeof(vis));
ncolor=0;
for(int i=s.size()-1;i>=0;i--) {
int j=s[i];
if(!vis[j]) ncolor++,dfs2(j);
}
}
int main()
{
int n,m;
cin>>n>>m;
while(m--){
int u,v;
cin>>u>>v;
G[u].push_back(v);
GT[v].push_back(u); //转置图
}
Korasaju(n);
return 0;
}