为什么我们要创建图的转置然后在第二遍中对转置运行dfs。我试图在线阅读正确性http://www.jeffreykarres.com/blog/kosaraju/证明,但不明白是否有其他方法可以做这很容易理解
这是我的算法实现,它以顶点和边的数量作为输入,然后以有向边作为输入(顶点从0到n-1编号)
#include <bits/stdc++.h>
using namespace std;
void dfsForward(int src,vector<vector<int>> g,vector<bool> &vis,stack<int> &s ){
vis[src]=true;
for(int i=0;i<g[src].size();i++){
if(!vis[g[src][i]])
dfsForward(g[src][i],g,vis,s);
}
s.push(src);
}
void dfsRev(int src,vector<vector<int>> t,vector<int> &comp,int count ){
vis[src]=true;
for(int i=0;i<t[src].size();i++){
if(!vis[t[src][i]]){
comp.push_back(t[src][i]);
dfsRev(t[src][i],t,comp,count);
}
}
}
vector<vector<int>> kosaraju(vector<vector<int>> g,int n){
vector<bool> vis(n,false);
vector<bool> visRev(n,false);
vector<vector<int>> scc;
int count=0;
stack<int> s;
for(int i=0;i<n;i++){
if(!vis[i])
dfsForward(i,s);
}
while(!s.empty()){
int temp =s.top();
s.pop();
if(!visRev[temp]){
count++;
vector<int> comp;
comp.push_back(temp);
dfsRev(temp,visRev,count);
scc.push_back(comp);
}
}
return scc;
}
int main() {
int n,e,u,v;
cin>>n>>e;
vector<vector<int>> g(n);
vector<vector<int>> t(n);
for(int i=0;i<e;i++){
cin>>u>>v;
g[u].push_back(v);
t[v].push_back(u);
}
cout<<"components are "<<endl;
vector<vector<int>> scc = kosaraju(g,n);
for(int i=0;i<scc.size();i++){
vector<int> arr = scc[i];
for(int j=0;j<arr.size();j++){
cout<<arr[j]<<" ";
}
cout<<endl;
}
return 0;
}