O ( V+E )
bool vis[maxn];
int time; // 时间戳
int num; // 连通分量的个数
int order[maxn]; // 记录dfs的后序
int belong[maxn]; //记录属于哪个连通分量
void dfs(int p){
vis[p]=true;
for(int i=map[p].size()-1;i>=0;i--)
if(!vis[map[p][i]])
dfs(map[p][i]);
order[time++]=p; // 一定要后序排序,才能保证逆序dfs时访问的首结点是顺序dfs时最后一棵树的根
}
void rdfs(int p){
vis[p]=true;
belong[p]=num;
for(int i=rmap[p].size()-1;i>=0;i--)
if(!vis[rmap[p][i]])
rdfs(rmap[p][i]);
}
void korasaju(){
memset(vis,false,sizeof(vis));
time=0;
for(int i=0;i<n;i++)
if(!vis[i]) dfs(i);
memset(vis,false,sizeof(vis));
num=0;
for(int i=n-1;i>=0;i--)
if(!vis[order[i]]){
num++;
rdfs(order[i]);
}
}