为什么我们要创建图形的转置,然后在第二遍中在转置上运行 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<bool> &vis, 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,vis,comp,count);
}
}
}
vector<vector<int>> kosaraju(vector<vector<int>> g,vector<vector<int>> t, 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,g,vis,s);
}
while(!s.empty()){
int temp =s.top();
s.pop();
if(!visRev[temp]){
count++;
vector<int> comp;
comp.push_back(temp);
dfsRev(temp,t,visRev,comp,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,t,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;
}