【问题标题】:why does kosaraju algorithm works and what is the idea behind it and is this a correct implementation?为什么 kosaraju 算法有效,它背后的想法是什么,这是一个正确的实现吗?
【发布时间】:2021-01-21 13:08:16
【问题描述】:

为什么我们要创建图形的转置,然后在第二遍中在转置上运行 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;
}

【问题讨论】:

  • 请格式化您的问题。看不懂……
  • 对不起,我现在尝试格式化。
  • 你真的应该使用描述性的变量名,而不是像tg这样的单字母名称。

标签: c++ algorithm graph connected-components kosaraju-algorithm


【解决方案1】:

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 循环,我的意思是图 G 的每个顶点中的 dfs)。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-12
    • 2014-06-09
    • 2010-09-15
    • 2012-06-13
    • 2011-11-06
    • 2018-08-12
    • 1970-01-01
    • 2021-12-22
    相关资源
    最近更新 更多