kosaraju Algorithm

The Kosaraju algorithm is an efficient and widely-used graph algorithm for finding the strongly connected components (SCCs) in a directed graph. Strongly connected components are subgraphs where every vertex is reachable from every other vertex within the same subgraph. These components play a crucial role in understanding the structure and organization of graphs, as well as solving various graph-related problems such as network analysis, circuit design, and program optimization. The algorithm, named after its inventor S. Rao Kosaraju, is based on the observation that the SCCs of a graph and its transpose (obtained by reversing the direction of all edges) are the same. The Kosaraju algorithm consists of two main steps. In the first step, a depth-first search (DFS) is performed on the original graph to compute a postorder traversal of all its vertices. This step essentially involves visiting all reachable vertices in a depth-first manner and recording the order in which they are visited. In the second step, the transpose of the graph is created and another DFS is performed on it, but this time the traversal starts from the vertex with the highest postorder value obtained in the first step. Whenever the DFS is completed for a vertex, a new SCC is found, and the process is repeated for the remaining vertices in decreasing order of their postorder values. The algorithm has a time complexity of O(V+E), where V is the number of vertices and E is the number of edges in the graph, making it highly efficient for finding SCCs in large graphs.
/* Implementation of Kosaraju's Algorithm to find out the strongly connected components (SCCs) in a graph. 
   Author:Anirban166
*/   

#include<iostream>
#include<vector>

using namespace std;

/**
* Iterative function/method to print graph:
* @param a[] : array of vectors (2D)
* @param V : vertices
* @return void 
**/
void print(vector<int> a[],int V)
{
    for(int i=0;i<V;i++)
    {
        if(!a[i].empty())
            cout<<"i="<<i<<"-->";
        for(int j=0;j<a[i].size();j++)
            cout<<a[i][j]<<" ";
        if(!a[i].empty())
            cout<<endl;
    }
}

/**
* //Recursive function/method to push vertices into stack passed as parameter:
* @param v : vertices
* @param &st : stack passed by reference
* @param vis[] : array to keep track of visited nodes (boolean type)
* @param adj[] : array of vectors to represent graph
* @return void 
**/
void push_vertex(int v,stack<int> &st,bool vis[],vector<int> adj[])
{
    vis[v]=true;
    for(auto i=adj[v].begin();i!=adj[v].end();i++)
    {
        if(vis[*i]==false)
            push_vertex(*i,st,vis,adj);
    }
    st.push(v);
}


/**
* //Recursive function/method to implement depth first traversal(dfs):
* @param v : vertices
* @param vis[] : array to keep track of visited nodes (boolean type)
* @param grev[] : graph with reversed edges
* @return void 
**/
void dfs(int v,bool vis[],vector<int> grev[])
{
    vis[v]=true;
    // cout<<v<<" ";
    for(auto i=grev[v].begin();i!=grev[v].end();i++)
    {
        if(vis[*i]==false)
            dfs(*i,vis,grev);
    }
}

//function/method to implement Kosaraju's Algorithm:
/**
* Info about the method
* @param V : vertices in graph
* @param adj[] : array of vectors that represent a graph (adjacency list/array)
* @return int ( 0, 1, 2..and so on, only unsigned values as either there can be no SCCs i.e. none(0) or there will be x no. of SCCs (x>0))
   i.e. it returns the count of (number of) strongly connected components (SCCs) in the graph. (variable 'count_scc' within function)
**/
int kosaraju(int V, vector<int> adj[])
{
    bool vis[V]={};
    stack<int> st;
    for(int v=0;v<V;v++)
    {
        if(vis[v]==false)
            push_vertex(v,st,vis,adj);
    }
    //making new graph (grev) with reverse edges as in adj[]:
    vector<int> grev[V];
    for(int i=0;i<V+1;i++)
    {
        for(auto j=adj[i].begin();j!=adj[i].end();j++)
        {
            grev[*j].push_back(i);
        }
    }
    // cout<<"grev="<<endl; ->debug statement
    // print(grev,V);       ->debug statement
    //reinitialise visited to 0
    for(int i=0;i<V;i++)
        vis[i]=false;
    int count_scc=0;
    while(!st.empty())
    {
        int t=st.top();
        st.pop();
        if(vis[t]==false)
        {
            dfs(t,vis,grev);
            count_scc++;
        }
    }
    // cout<<"count_scc="<<count_scc<<endl; //in case you want to print here itself, uncomment & change return type of function to void.
    return count_scc;
}

//All critical/corner cases have been taken care of.
//Input your required values: (not hardcoded)
int main()
{
    int t;
    cin>>t; 
    while(t--)
    {
        int a,b ; //a->number of nodes, b->directed edges.
   	  cin>>a>>b;
   	  int m,n;
   	  vector<int> adj[a+1];
        for(int i=0;i<b;i++) //take total b inputs of 2 vertices each required to form an edge.
        {
            cin>>m>>n; //take input m,n denoting edge from m->n.
            adj[m].push_back(n);
        }
        //pass number of nodes and adjacency array as parameters to function:
        cout<<kosaraju(a, adj)<<endl;
    }
    return 0;
}

LANGUAGE:

DARK MODE: