bridge finding with tarjan algorithm Algorithm

The Tarjan's algorithm is an efficient graph traversal technique used for finding strongly connected components (SCCs) in a directed graph. SCCs are sets of vertices in a graph that are highly connected, where each vertex in a set can be reached from any other vertex in the same set by following a sequence of directed edges. SCCs help identify the structure of a graph and are useful in various applications, such as analyzing social networks, optimizing transportation systems, and detecting cycles in dependency graphs. The algorithm, designed by Robert Tarjan in 1972, is based on the depth-first search (DFS) method and leverages a stack data structure to keep track of visited nodes. The primary idea behind Tarjan's algorithm is to assign a unique index to each vertex during its first visit in the DFS traversal and maintain a low-link value that represents the smallest index reachable from the current vertex, including itself. The algorithm uses a stack to store the vertices visited during the traversal and keeps track of whether a vertex is still present in the stack. When the low-link value of a vertex equals its index, it indicates that the vertex is the root of a strongly connected component, and all the vertices in the stack up to the root vertex form an SCC. The algorithm then pops these vertices from the stack and continues the traversal. Tarjan's algorithm is highly efficient, with a linear time complexity of O(V+E), where V and E represent the number of vertices and edges in the graph, respectively.
/*
 *  Copyright : 2020 , MIT
 *  Author : Amit Kumar (offamitkumar)
 *  Last Modified Date: May 24, 2020
 *
 */
#include <vector>  //  for std::vector
#include <algorithm>  //  for min & max
#include <iostream>  //  for cout
using std::vector;
using std::cout;
using std::min;
class Solution {
    vector < vector < int > > graph;
    vector<int>in_time , out_time;
    int timer;
    vector < vector < int > > bridge;
    vector<bool>visited;
    void dfs(int current_node , int parent) {
        visited.at(current_node) = true;
        in_time[current_node] = out_time[current_node] = timer++;
        for ( auto&itr : graph[current_node] ) {
            if (itr == parent) {
                continue;
            }
            if (!visited[itr]) {
                dfs(itr , current_node);
                if (out_time[itr] > in_time[current_node]) {
                    bridge.push_back({itr, current_node});
                }
            }
            out_time[current_node] = min(out_time[current_node], out_time[itr]);
        }
    }

 public:
    vector <vector <int> > search_bridges(int n,
            const vector<vector<int>>& connections) {
        timer = 0;
        graph.resize(n);
        in_time.assign(n, 0);
        visited.assign(n, false);
        out_time.assign(n, 0);
        for (auto&itr : connections) {
            graph.at(itr[0]).push_back(itr[1]);
            graph.at(itr[1]).push_back(itr[0]);
        }
        dfs(0, -1);
        return bridge;
    }
};
int main(void) {
    Solution s1;
    int number_of_node = 5;
    vector< vector <int> >node;
    node.push_back({0, 1});
    node.push_back({1, 3});
    node.push_back({1, 2});
    node.push_back({2, 4});
    /*
     *     0 <--> 1 <---> 2
     *            ^       ^
     *            |       |
     *            |       |
     *            \/     \/
     *            3       4
     *
     *    In this graph there are 4 bridges [0,2] , [2,4] , [3,5] , [1,2]
     *    
     *    I assumed that the graph is bi-directional and connected.
     *
     */
    vector< vector <int> > bridges = s1.search_bridges(number_of_node , node);
    cout << bridges.size() << " bridges found!\n";
    for (auto&itr : bridges) {
        cout << itr[0] << " --> " << itr[1] << '\n';
    }
    return 0;
}

LANGUAGE:

DARK MODE: