Launch your tech mastery with us—your coding journey starts now!
Course Content
Data Structure

Strongly Connected Components (SCC)

Definition

A Strongly Connected Component (SCC) is a specific group of nodes within a Directed Graph. In this group, you can start at any node and reach every other node in the same group by following the arrows (edges).

Strongly Connected Components (SCC) illustration showing a directed graph divided into groups where each node in a group is reachable from every other node in the same group.

How it Works

Think of a directed graph like a city with one-way streets.

  1. The Rule: If you can drive from House A to House B and figure out a way to drive back from House B to House A, then A and B are in the same Strongly Connected Component.
  2. The Cycle: SCCs essentially define “cycles” or loops in a graph. If you can leave a group but never return, you have crossed into a different component.
  3. Partition: Every node in a directed graph belongs to exactly one SCC.

Real-World Analogy

City Neighborhoods:

Imagine a city divided into neighborhoods by highways.

  • Inside a neighborhood (The SCC): The streets are a maze of one-way roads, but if you know the way, you can eventually get from any house to any other house within that neighborhood.
  • Between neighborhoods: Once you take the highway exit to go to the “North Side,” you might not be able to come back to the “South Side” because the highway only goes one way. The “South Side” is one SCC, and the “North Side” is another.

Example

Graph:

  • A rightarrow B
  • B rightarrow C
  • C rightarrow A (This creates a loop: A-B-C-A)
  • B rightarrow D (One way street to D)

Components:

  1. {A, B, C}: You can travel between all of them.
  2. {D}: Once you are at D, you cannot go back to A, B, or C. D is its own component.

Code Example (Kosaraju’s Algorithm)

Note: This algorithm uses two passes of DFS to find these groups.

PythonJavaCC++

from collections import defaultdict

class Graph:

    def __init__(self, vertices):
        self.V = vertices
        self.graph = defaultdict(list)

    # Add directed edge
    def add_edge(self, u, v):
        self.graph[u].append(v)

    # Step 1: DFS and fill stack by finish time
    def fill_order(self, v, visited, stack):

        visited.add(v)

        for i in self.graph[v]:
            if i not in visited:
                self.fill_order(i, visited, stack)

        stack.append(v)


    # Step 2: Reverse graph
    def get_transpose(self):

        g = Graph(self.V)

        for i in self.graph:
            for j in self.graph[i]:
                g.add_edge(j, i)

        return g


    # Step 3: DFS to print component
    def dfs_print(self, v, visited):

        visited.add(v)
        print(v, end=" ")

        for i in self.graph[v]:
            if i not in visited:
                self.dfs_print(i, visited)


    # Main function for SCC
    def print_sccs(self):

        stack = []
        visited = set()

        # Fill stack
        for i in range(self.V):
            if i not in visited:
                self.fill_order(i, visited, stack)

        # Reverse graph
        gr = self.get_transpose()

        visited.clear()

        # Process stack
        while stack:

            i = stack.pop()

            if i not in visited:
                gr.dfs_print(i, visited)
                print()


# Example
g = Graph(5)

g.add_edge(1,0)
g.add_edge(0,2)
g.add_edge(2,1)
g.add_edge(0,3)
g.add_edge(3,4)

print("Strongly Connected Components:")
g.print_sccs()

import java.util.*;

class Graph {

    int V;
    LinkedList<Integer> adj[];

    Graph(int v) {

        V = v;
        adj = new LinkedList[v];

        for (int i = 0; i < v; ++i)
            adj[i] = new LinkedList<>();
    }

    void addEdge(int v, int w) {
        adj[v].add(w);
    }

    void fillOrder(int v, boolean visited[], Stack<Integer> stack) {

        visited[v] = true;

        for (int n : adj[v])
            if (!visited[n])
                fillOrder(n, visited, stack);

        stack.push(v);
    }

    Graph getTranspose() {

        Graph g = new Graph(V);

        for (int v = 0; v < V; v++)
            for (int i : adj[v])
                g.adj[i].add(v);

        return g;
    }

    void DFSUtil(int v, boolean visited[]) {

        visited[v] = true;

        System.out.print(v + " ");

        for (int n : adj[v])
            if (!visited[n])
                DFSUtil(n, visited);
    }

    void printSCCs() {

        Stack<Integer> stack = new Stack<>();

        boolean visited[] = new boolean[V];

        for (int i = 0; i < V; i++)
            if (!visited[i])
                fillOrder(i, visited, stack);

        Graph gr = getTranspose();

        Arrays.fill(visited, false);

        while (!stack.empty()) {

            int v = stack.pop();

            if (!visited[v]) {

                gr.DFSUtil(v, visited);
                System.out.println();
            }
        }
    }

    public static void main(String[] args) {

        Graph g = new Graph(5);

        g.addEdge(1,0);
        g.addEdge(0,2);
        g.addEdge(2,1);
        g.addEdge(0,3);
        g.addEdge(3,4);

        System.out.println("Strongly Connected Components:");

        g.printSCCs();
    }
}

#include <stdio.h>

#define V 5

int graph[V][V] = {0};

void addEdge(int u, int v) {
    graph[u][v] = 1;
}

void dfs(int v, int visited[]) {

    visited[v] = 1;
    printf("%d ", v);

    for (int i = 0; i < V; i++)
        if (graph[v][i] && !visited[i])
            dfs(i, visited);
}

int main() {

    addEdge(1,0);
    addEdge(0,2);
    addEdge(2,1);
    addEdge(0,3);
    addEdge(3,4);

    int visited[V] = {0};

    printf("DFS Example (partial SCC logic):\n");

    dfs(0, visited);

    return 0;
}

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

class Graph {

public:
    int V;
    vector<vector<int>> adj;

    Graph(int v) {
        V = v;
        adj.resize(v);
    }

    void addEdge(int u, int v) {
        adj[u].push_back(v);
    }

    void dfs(int v, vector<bool>& visited) {

        visited[v] = true;
        cout << v << " ";

        for (int i : adj[v])
            if (!visited[i])
                dfs(i, visited);
    }
};

int main() {

    Graph g(5);

    g.addEdge(1,0);
    g.addEdge(0,2);
    g.addEdge(2,1);
    g.addEdge(0,3);
    g.addEdge(3,4);

    vector<bool> visited(5,false);

    cout << "DFS Example:" << endl;

    g.dfs(0, visited);

    return 0;
}

Complexity Analysis

  • Time Complexity: O(V + E). We traverse the graph (DFS) twice and reverse it once. All are linear operations.
  • Space Complexity: O(V). We need arrays to store visited status and the stack.

Use Cases

  • Social Media Analysis: Finding tight-knit communities where everyone follows everyone else.
  • Web Crawlers: Identifying “link farms” or groups of websites that link to each other to boost SEO rankings artificially.