Check if a graph is strongly connected

Last Updated : 9 Feb, 2026

Given a directed graph, find out whether the graph is strongly connected or not. A directed graph is strongly connected if there is a path between any two pair of vertices.

Example:

Input: adj[][] = [[1], [2], [3, 4], [0], [2]]

connectivity3-300x172

Output: Yes
Explanation: Every node is reachable from every other node in the component.

It is easy for undirected graph, we can just do a BFS and DFS starting from any vertex. If BFS or DFS visits all vertices, then the given undirected graph is connected. This approach won't work for a directed graph. For example, consider the following graph which is not strongly connected. If we start DFS (or BFS) from vertex 0, we can reach all vertices, but if we start from any other vertex, we cannot reach all vertices.
 

connectivity1

How to do for directed graph?

A simple idea is to use a all pair shortest path algorithm like Floyd Warshall or find Transitive Closure of graph. Time complexity of this method would be O(v3).
We can also do DFS V times starting from every vertex. If any DFS, doesn't visit all vertices, then graph is not strongly connected. This algorithm takes O(V*(V+E)) time which can be same as transitive closure for a dense graph.

A better idea can be Strongly Connected Components (SCC) algorithm. We can find all SCCs in O(V+E) time. If number of SCCs is one, then graph is strongly connected. The algorithm for SCC does extra work as it finds all SCCs. 

Following is Kosaraju's DFS based simple algorithm that does two DFS traversals of 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.

The idea is, if every node can be reached from a vertex v, and every node can reach v, then the graph is strongly connected. In step 2, we check if all vertices are reachable from v. In step 4, we check if all vertices can reach v (In reversed graph, if all vertices are reachable from v, then all vertices can reach v in original graph). 
Following is the implementation of above algorithm.
Implementation:

C++
#include <iostream>
#include <vector>
using namespace std;

// A recursive DFS based function
// This DFS marks all vertices reachable from vertex v
void dfsUtil(int v, vector<vector<int>> &adj, vector<bool> &visited) {

    // Mark the current vertex as visited
    visited[v] = true;

    // Visit all unvisited vertices reachable from v
    for (int u : adj[v]) {

        if (!visited[u]) {
            dfsUtil(u, adj, visited);
        }
    }
}

// Function that returns transpose of the graph
// Transpose graph is obtained by reversing all edges
vector<vector<int>> getTranspose(vector<vector<int>> &adj) {

    int n = adj.size();
    vector<vector<int>> transpose(n);

    // Reverse direction of every edge u -> v to v -> u
    for (int v = 0; v < n; v++) {

        for (int u : adj[v]) {
            transpose[u].push_back(v);
        }
    }

    return transpose;
}

// Function that returns true if graph
// is strongly connected, otherwise false
bool isStronglyConnected(vector<vector<int>> &adj) {

    int n = adj.size();
    vector<bool> visited(n, false);

    // Run DFS from vertex 0 in the original graph
    dfsUtil(0, adj, visited);

    // If some vertex is not reachable, graph is not strongly connected
    for (int i = 0; i < n; i++) {
        if (!visited[i]) {
            return false;
        }
    }

    // Get the transpose of the graph
    vector<vector<int>> revAdj = getTranspose(adj);

    // Reset visited array for second DFS
    fill(visited.begin(), visited.end(), false);

    // Run DFS from vertex 0 in the transposed graph
    dfsUtil(0, revAdj, visited);

    // If some vertex is not reachable in transpose, graph is not strongly connected
    for (int i = 0; i < n; i++) {
        if (!visited[i]) {
            return false;
        }
    }

    return true;
}

int main() {

    vector<vector<int>> g1(5);
    g1[0].push_back(1);
    g1[1].push_back(2);
    g1[2].push_back(3);
    g1[3].push_back(0);
    g1[2].push_back(4);
    g1[4].push_back(2);

    isStronglyConnected(g1) ? cout << "Yes\n" : cout << "No\n";
    
    vector<vector<int>> g2(4);
    g2[0].push_back(1);
    g2[1].push_back(2);
    g2[2].push_back(3);
    
    isStronglyConnected(g2) ? cout << "Yes\n" : cout << "No\n";

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Arrays;

class GFG {

    // A recursive DFS based function
    // This DFS marks all vertices reachable from vertex v
    static void dfsUtil(int v, int[][] adj, boolean[] visited) {

        // Mark the current vertex as visited
        visited[v] = true;

        // Visit all unvisited vertices reachable from v
        for (int u : adj[v]) {

            if (!visited[u]) {
                dfsUtil(u, adj, visited);
            }
        }
    }

    // Function that returns transpose of the graph
    // Transpose graph is obtained by reversing all edges
    static int[][] getTranspose(int[][] adj) {

        int n = adj.length;
        ArrayList<ArrayList<Integer>> temp = new ArrayList<>();

        for (int i = 0; i < n; i++) {
            temp.add(new ArrayList<>());
        }

        // Reverse direction of every edge u -> v to v -> u
        for (int v = 0; v < n; v++) {

            for (int u : adj[v]) {
                temp.get(u).add(v);
            }
        }

        int[][] transpose = new int[n][];
        for (int i = 0; i < n; i++) {
            transpose[i] = temp.get(i).stream().mapToInt(x -> x).toArray();
        }

        return transpose;
    }

    // Function that returns true if graph
    // is strongly connected, otherwise false
    static boolean isStronglyConnected(int[][] adj) {

        int n = adj.length;
        boolean[] visited = new boolean[n];

        // Run DFS from vertex 0 in the original graph
        dfsUtil(0, adj, visited);

        // If some vertex is not reachable, graph is not strongly connected
        for (boolean v : visited) {
            if (!v) {
                return false;
            }
        }

        // Get the transpose of the graph
        int[][] revAdj = getTranspose(adj);

        // Reset visited array for second DFS
        Arrays.fill(visited, false);

        // Run DFS from vertex 0 in the transposed graph
        dfsUtil(0, revAdj, visited);

        // If some vertex is not reachable in transpose, graph is not strongly connected
        for (boolean v : visited) {
            if (!v) {
                return false;
            }
        }

        return true;
    }

    public static void main(String[] args) {

        int[][] g1 = {{1}, {2}, {3, 4}, {0}, {2}};
        System.out.println(isStronglyConnected(g1) ? "Yes" : "No");
        
        int[][] g2 = {{1}, {2}, {3},{}};
        System.out.println(isStronglyConnected(g2) ? "Yes" : "No");

    }
}
Python
# A recursive DFS based function
# This DFS marks all vertices reachable from vertex v
def dfsUtil(v, adj, visited):

    # Mark the current vertex as visited
    visited[v] = True

    # Visit all unvisited vertices reachable from v
    for u in adj[v]:

        if not visited[u]:
            dfsUtil(u, adj, visited)


# Function that returns transpose of the graph
# Transpose graph is obtained by reversing all edges
def getTranspose(adj):

    n = len(adj)
    transpose = [[] for _ in range(n)]

    # Reverse direction of every edge u -> v to v -> u
    for v in range(n):

        for u in adj[v]:
            transpose[u].append(v)

    return transpose


# Function that returns true if graph
# is strongly connected, otherwise false
def isStronglyConnected(adj):

    n = len(adj)
    visited = [False] * n

    # Run DFS from vertex 0 in the original graph
    dfsUtil(0, adj, visited)

    # If some vertex is not reachable, graph is not strongly connected
    if not all(visited):
        return False

    # Get the transpose of the graph
    revAdj = getTranspose(adj)

    # Reset visited array for second DFS
    visited = [False] * n

    # Run DFS from vertex 0 in the transposed graph
    dfsUtil(0, revAdj, visited)

    # If some vertex is not reachable in transpose, graph is not strongly connected
    if not all(visited):
        return False

    return True


if __name__ == "__main__":

    g1 = [[1], [2], [3, 4], [0], [2]]
    print("Yes" if isStronglyConnected(g1) else "No")
    
    g2 = [[1], [2], [3], []]
    print("Yes" if isStronglyConnected(g2) else "No")
C#
using System;
using System.Collections.Generic;

class GFG {

    // A recursive DFS based function
    // This DFS marks all vertices reachable from vertex v
    static void dfsUtil(int v, List<List<int>> adj, bool[] visited) {

        // Mark the current vertex as visited
        visited[v] = true;

        // Visit all unvisited vertices reachable from v
        foreach (int u in adj[v]) {

            if (!visited[u]) {
                dfsUtil(u, adj, visited);
            }
        }
    }

    // Function that returns transpose of the graph
    // Transpose graph is obtained by reversing all edges
    static List<List<int>> getTranspose(List<List<int>> adj) {

        int n = adj.Count;
        var transpose = new List<List<int>>();

        for (int i = 0; i < n; i++) {
            transpose.Add(new List<int>());
        }

        // Reverse direction of every edge u -> v to v -> u
        for (int v = 0; v < n; v++) {

            foreach (int u in adj[v]) {
                transpose[u].Add(v);
            }
        }

        return transpose;
    }

    // Function that returns true if graph
    // is strongly connected, otherwise false
    static bool isStronglyConnected(List<List<int>> adj) {

        int n = adj.Count;
        bool[] visited = new bool[n];

        // Run DFS from vertex 0 in the original graph
        dfsUtil(0, adj, visited);

        // If some vertex is not reachable, graph is not strongly connected
        foreach (bool v in visited) {
            if (!v) {
                return false;
            }
        }

        // Get the transpose of the graph
        var revAdj = getTranspose(adj);

        // Reset visited array for second DFS
        Array.Fill(visited, false);

        // Run DFS from vertex 0 in the transposed graph
        dfsUtil(0, revAdj, visited);

        // If some vertex is not reachable in transpose, graph is not strongly connected
        foreach (bool v in visited) {
            if (!v) {
                return false;
            }
        }

        return true;
    }

    static void Main() {

        var g1 = new List<List<int>> {
            new List<int>{1},
            new List<int>{2},
            new List<int>{3,4},
            new List<int>{0},
            new List<int>{2}
        };

        Console.WriteLine(isStronglyConnected(g1) ? "Yes" : "No");
        
        var g2 = new List<List<int>> {
            new List<int>{1},
            new List<int>{2},
            new List<int>{3},
            new List<int>()
        };
        
        Console.WriteLine(isStronglyConnected(g2) ? "Yes" : "No");
    }
}
JavaScript
// A recursive DFS based function
// This DFS marks all vertices reachable from vertex v
function dfsUtil(v, adj, visited) {

    // Mark the current vertex as visited
    visited[v] = true;

    // Visit all unvisited vertices reachable from v
    for (let u of adj[v]) {

        if (!visited[u]) {
            dfsUtil(u, adj, visited);
        }
    }
}

// Function that returns transpose of the graph
// Transpose graph is obtained by reversing all edges
function getTranspose(adj) {

    let n = adj.length;
    let transpose = Array.from({ length: n }, () => []);

    // Reverse direction of every edge u -> v to v -> u
    for (let v = 0; v < n; v++) {

        for (let u of adj[v]) {
            transpose[u].push(v);
        }
    }

    return transpose;
}

// Function that returns true if graph
// is strongly connected, otherwise false
function isStronglyConnected(adj) {

    let n = adj.length;
    let visited = Array(n).fill(false);

    // Run DFS from vertex 0 in the original graph
    dfsUtil(0, adj, visited);

    // If some vertex is not reachable, graph is not strongly connected
    if (visited.includes(false)) {
        return false;
    }

    // Get the transpose of the graph
    let revAdj = getTranspose(adj);

    // Reset visited array for second DFS
    visited.fill(false);

    // Run DFS from vertex 0 in the transposed graph
    dfsUtil(0, revAdj, visited);

    // If some vertex is not reachable in transpose, graph is not strongly connected
    if (visited.includes(false)) {
        return false;
    }

    return true;
}

// Driver Code
let g1 = [[1], [2], [3, 4], [0], [2]];
console.log(isStronglyConnected(g1) ? "Yes" : "No");

let g2 = [[1], [2], [3], []];
console.log(isStronglyConnected(g2) ? "Yes" : "No");

Output
Yes
No

Time Complexity: Time complexity of above implementation is same as Depth First Search which is O(V+E) if the graph is represented using adjacency list representation.

Auxiliary Space: O(V)

Can we improve further? 
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.

Exercise: 
Can we use BFS instead of DFS in above algorithm? See this.

Comment