Kosaraju's Algorithm in C

Kosaraju's Algorithm in C is one of the most basic concepts in graph theory and algorithms. In a directed graph, a Strongly Connected Component is a set of vertices such that every vertex is reachable from every other vertex by using the directed edges. The problem of finding all the SCCs for a graph makes for an interesting case study, and a solution to this problem can be applied in a variety of ways. This data can provide insights about the structure and connectivity of the graph, and it has many applications in fields such as social networks, social network analysis, web crawling, and network routing.

What is Kosaraju's Algorithm?

A directed graph is said to be strongly connected if you can traverse from any vertex to any other vertex within that component. A single directed graph can have multiple strongly connected components Connectivity in a graph refers to whether two vertices are reachable from each other or not. If you define connectivity in terms of a path, you can say two vertices are considered connected if a path exists from one vertex to another.

Kosaraju's algorithm is a depth-first search (DFS) based algorithm used to find all Strongly Connected Components (SCCs) of a directed graph. The beauty of the algorithm lies in the fact that it compactly merges all the reachable vertices into a single SCC. In other words, the algorithm finds all the SCCs for the graph and returns a subgraph that contains all reachable vertices.

The algorithm works in two main phases.

  • Run a DFS on the original graph and push the vertices in a stack because they are finished or marked as back in the backtracking. We do not find the SCCs for the original graph in this step; we just find the finish times.
  • Reverse the direction of all the edges in the graph, and then run it again using the same DFS process as before: First, reset all the finish times of all the vertices that we saved in the first step. After this step, each subsequent call to this DFS will return one SCC.

The steps for implementing kosaraju's algorithm to find all strongly connected components of a directed graph are outlined below:

Steps:

  • Perform a depth-first search (DFS) traversal of the directed graph being considered with an empty stack (or any type of data structure that allows for DFS). The search operation is performed on the vertices.
  • After that, Reverse the direction of each edge in the graph to get a new graph with the same vertices but in reversed directions. This direction reversal can be done by switching the source vertex to the destination vertex for each edge.
  • Next, begin taking vertices off the stack one by one, and then perform DFS on the reversed graph for each vertex popped off the stack. After performing DFS on each vertex popped off the stack, the set of vertices reached together in a single traversal/DFS will relate to the strongly connected component associated with the selected vertex.
  • Continue to repeat step 3 until the stack is empty. Every time a DFS is performed for a vertex stacked, there will be a new strongly connected component associated with the vertex popped from the stack.
  • Kosaraju's method returned the extra new strongly connected components from a DFS traversal on the reversed graph in step 3. The components represent the strongly connected groups of vertices in the directed graph, and each strongly connected component is characterized by inter-vertex connectivity.

What is the use implement Kosaraju's algorithm?

Kosaraju's algorithm applies to directed graphs to find strongly connected components. Strongly connected components are sets of vertices in which there exists at least one directed path from every vertex in a strongly connected component to every other vertex in that same strongly connected component.

The considerations for applying Kosaraju's algorithm in directed graphs include:

  • Time Complexity Efficiency: The time complexity of Kosaraju's algorithm is O(V + E), where V and E correspond to the number of vertices and edges in the directed graph. You emphasize that O(V + E) is linear time complexity, which makes Kosaraju's algorithm particularly compelling for use in not just large graphs but in real-world modelling situations where any persistent practical implementation will be a large graph.
  • Simplicity and Implementability Iteration: Kosaraju's algorithm has very well-defined and simple instructions compared with other strongly connected component searching algorithms, such as Tarjan's or Gabow's. Kosaraju's algorithm is simply and aptly characterized as the two-phase depth-first-search (DFS) process, a DFS process followed by another DFS process but on the reverse directed graph.
  • Finding Strongly Connected Components: As there are some distinct considerations for using Kosaraju's algorithm, you note that strongly connected components have widely desired applications in database management, network analysis, Social networks, or constructing a compiler. Finding strongly connected components displays the structure and behaviour of the information contained in directed graphs, but finding strongly connected components can also offer values engaged in practical problem-solving.
  • Robust: Kosaraju's algorithm finds and identifies all strongly connected components in a directed graph, regardless of the directed graph being fully or partially disconnected. Kosaraju's algorithm will find strongly connected components regardless of whether the directed graph is fully partitioned or the vertices cannot be fully or partially reached from one another.
  • Flexibility: The algorithm can be adapted for other-directed graph analytical and study purposes. For example, Kosaraju's algorithm could be adapted for use in directed graphs for k largest strongly connected components based on the number of vertices, or findings strongly connected components based on other conditional metrics.

Working of Kosaraju's Algorithm:

In directed networks, Kosaraju's algorithm identifies strong connected components (SCCs) in linear time. It can be called a Forward Stage and a Reverse Stage. The following is a general overview of how the algorithm works:

1. Forward Stage

Begin with an arbitrary vertex in the graph, and depth-first search (DFS) it. By doing this DFS, each vertex will be given a "Finish time" for when each vertex finished during the DFS traversal.

Make a record of the vertices according to the order of finish time, most likely with a stack of vertices as they are completed.

2. Reverse Stage

Reverse the direction of each edge to transpose and then the vertices are poped from the stack. The DFS search is performed on the transposed graph. In this step, the original graph has identified a strongly connected component originating from the DFS performed at the popped vertex.

Example:

Output:

 
The Strongly Connected components of the graph are:
0 2 1
3
4   

Explanation:

Approach:

The functions below are used to find Strongest Connected Components.

Graph Structure:

The Graph structure graph is defined that contains:

  • Int vertex: This represents the number of vertices present in the graph.
  • Int adjM[MAX][MAX]: An adjacency matrix for representing the edges among vertices, the value of MAX is predefined and represents the maximum number of vertices

Stack Structure: The stack structure is used to store the order of vertices during the time of DFS traversal.

  • Int item[MAX]: An array that will be used to store all stack items.
  • Int peek: An integer is used to indicate the top of the stack. Initially, -1 is set to represent an empty stack.

Functions:

  • The code uses few functions to perform the required algorithm:
  • Creation of Stack: Function(creationOfStack) will be used to create a new stack, it allocates the memory to the stack and initializes the peek index to -1.
  • Push the item and Pop the item: Push and pop process elements to be pushed and pop. The push function will be used to push a vertex in the stack by increasing the peek index, while the function pop will be used to pop the vertex from the stack and decrease the peek index.
  • Check if Stack is Empty: The StackisEmpty will be used to check if the stack is empty.

DFS:

The function dfs must be implemented to perform Depth-First-Search on the original graph. Mark the current vertex as visit.

  • Transpose of the Graph: The Function getGraphTranspose will transpose the graph.
  • DFS on Transpose Graph: Similarly to the first DFS, we will implement the function DFS on the transposed graph.

Kosaraju's Algorithm:

The core function, kosarajuAlgo, runs the algorithm:

  • First DFS call: It iterates over all vertices and calls the dfsfunction to fill the stack based on finishing times.
  • Transpose the graph: It calls getGraphTransposeto create a transposed graph.
  • Reset visited array: We reset the visited array to keep track of the second DFS accurately.
  • Second DFS call: It pops vertices from the stack and calls dfsTransposeGraphfor the unvisited vertices discovered in the pop. It allows us to find and print the SCCs.

Main Function:

Sets up the number of vertices. Initializes the adjacency matrix to zero. After that, adds directed edges to the graph as specified. Finally, it calls kosarajuAlgo to run the algorithm and print the Strongly Connected Components it finds.

Conclusion:

In conclusion, Kosaraju's Algorithm represents an efficient and effective method for finding Strongly Connected Components (SCCs) in directed graphs. This method, performing in O(V + E) time, is particularly useful for large graphs to touch upon its practical usage in many applications such as social network analysis, web crawling, and network routing.

Kosaraju's simple and flexible algorithm consists of two depth-first searches (DFS) of the directed graph. By reversing the graph and utilizing the stack to determine the order of vertex processing, the algorithm accurately identifies SCCs regardless of whether the directed graph is connected.