Open In App

Kosaraju’s Algorithm in C++

Last Updated : 01 Aug, 2024
Summarize
Comments
Improve
Suggest changes
Like Article
Like
Share
Report
News Follow

In this post, we will see the implementation of Kosaraju’s Algorithm in C++.

What is Kosaraju’s Algorithm?

Kosaraju’s Algorithm is a classic algorithm used for finding strongly connected components (SCCs) in a directed graph. An SCC is a maximal subgraph where every vertex is reachable from every other vertex in the subgraph. This algorithm is widely used in various applications such as finding cycles in a graph, circuit design, and network analysis.

Below is an example of a strongly connected graph:

connectivity
Strongly connected

How does Kosaraju’s Algorithm Work in C++?

The algorithm works in two main phases:

  1. Perform a Depth-First Search (DFS) on the original graph and store the vertices in a stack according to their finish times.
  2. Transpose (reverse) the graph and perform DFS using the vertices in the order defined by the stack to identify the SCCs.

Steps of Kosaraju’s Algorithm to Implement in C++

Following are steps of Kosaraju’s DFS-based simple algorithm that does two DFS traversals of the graph: 

  1. Initialize all vertices as not visited.
  2. Do a DFS traversal of graph starting from any arbitrary vertex v. If DFS traversal doesn’t visit all vertices, then return false.
  3. Reverse all arcs (or find transpose or reverse of graph) 
  4. Mark all vertices as not-visited in reversed graph.
  5. Do a DFS traversal of reversed graph starting from same vertex v (Same as step 2). If DFS traversal doesn’t visit all vertices, then return false. Otherwise return true.

C++ Program to Implement Kosaraju’s Algorithm

Below is a C++ program that implements Kosaraju’s Algorithm for finding strongly connected components:

// C++ program to implement Kosaraju’s algorithm to check if
// a given directed graph is strongly connected or not

#include <iostream>
#include <list>
#include <stack>
using namespace std;

class Graph {
    // No. of vertices
    int V;
    // An array of adjacency lists
    list<int>* adj;

    // A recursive function to print DFS
    // starting from v
    void DFSUtil(int v, bool visited[]);

public:
    // Constructor and Destructor
    Graph(int V)
    {
        this->V = V;
        adj = new list<int>[V];
    }
    ~Graph() { delete[] adj; }

    // Method to add an edge
    void addEdge(int v, int w);

    // The main function that returns true if the
    // graph is strongly connected, otherwise false
    bool isSC();

    // Function that returns reverse (or transpose)
    // of this graph
    Graph getTranspose();
};

// A recursive function to print DFS starting from v
void Graph::DFSUtil(int v, bool visited[])
{
    // Mark the current node as visited and print it
    visited[v] = true;

    // Recur for all the vertices adjacent to this vertex
    list<int>::iterator i;
    for (i = adj[v].begin(); i != adj[v].end(); ++i)
        if (!visited[*i])
            DFSUtil(*i, visited);
}

// Function that returns reverse (or transpose) of this
// graph
Graph Graph::getTranspose()
{
    Graph g(V);
    for (int v = 0; v < V; v++) {
        // Recur for all the vertices adjacent to this
        // vertex
        list<int>::iterator i;
        for (i = adj[v].begin(); i != adj[v].end(); ++i) {
            g.adj[*i].push_back(v);
        }
    }
    return g;
}

void Graph::addEdge(int v, int w)
{
    // Add w to v’s list.
    adj[v].push_back(w);
}

// The main function that returns true if graph
// is strongly connected
bool Graph::isSC()
{
    // St1p 1: Mark all the vertices as not visited
    // (For first DFS)
    bool visited[V];
    for (int i = 0; i < V; i++)
        visited[i] = false;

    // Step 2: Do DFS traversal starting from first vertex.
    DFSUtil(0, visited);

    // If DFS traversal doesn’t visit all vertices,
    // then return false.
    for (int i = 0; i < V; i++)
        if (visited[i] == false)
            return false;

    // Step 3: Create a reversed graph
    Graph gr = getTranspose();

    // Step 4: Mark all the vertices as not visited
    // (For second DFS)
    for (int i = 0; i < V; i++)
        visited[i] = false;

    // Step 5: Do DFS for reversed graph starting from
    // first vertex. Starting Vertex must be same starting
    // point of first DFS
    gr.DFSUtil(0, visited);

    // If all vertices are not visited in second DFS, then
    // return false
    for (int i = 0; i < V; i++)
        if (visited[i] == false)
            return false;

    return true;
}

int main()
{
    // Create graphs given in the above diagrams
    Graph g1(5);
    g1.addEdge(0, 1);
    g1.addEdge(1, 2);
    g1.addEdge(2, 3);
    g1.addEdge(3, 0);
    g1.addEdge(2, 4);
    g1.addEdge(4, 2);
    g1.isSC() ? cout << "Yes\n" : cout << "No\n";

    Graph g2(4);
    g2.addEdge(0, 1);
    g2.addEdge(1, 2);
    g2.addEdge(2, 3);
    g2.isSC() ? cout << "Yes\n" : cout << "No\n";

    return 0;
}

Output
Yes
No

Time Complexity: O(V + E), where V is the number of vertices and E is the number of edges. Each vertex and edge is processed exactly once in both DFS traversals.
Auxiliary Space: O(V) for storing the visited array and stack.

Note: The above approach requires two traversals of graph. We can find whether a graph is strongly connected or not in one traversal using Tarjan’s Algorithm to find Strongly Connected Components.


Next Article
Article Tags :
Practice Tags :

Similar Reads

three90RightbarBannerImg