为什么kosaraju算法有效,其背后的思想是什么,这是正确的实现吗?

为什么我们要创建图的转置然后在第二遍中对转置运行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;
}
blackless 回答:为什么kosaraju算法有效,其背后的思想是什么,这是正确的实现吗?

Kosaraju 算法只需三个简单的步骤:

1.Reverse the Graph.

2. Apply DFS-Loop in Reverse Graph and calculate ordering of each vertex (we call 
   it finishig times).
3. Apply DFS-loops in Graph in descending order of finishing times.

(通过 DFS-Loop 我指的是图 G 的每个顶点中的 dfs)。

回答你的问题:为什么我们首先反转图表 步骤???..

如您所知,图 G 和反向图 G' 中的 SCC 将始终相同。如果您将每个 SCC 视为一个单独的节点 N,G 和 G' 将是 DAG(直接无环图)。作为 DFS 的一个属性,DAG 中最大的完成时间将始终是 Graph 的同步顶点(没有输出弧的顶点),在这种情况下为 N。所以如果你从这个同步顶点 N 重新运行 DFS,它只会迭代那个特定的 SCC(形成 N)。因此,通过这种方式迭代,您将发现图中的所有 SCC。

本文链接:https://www.f2er.com/1443395.html

大家都在问