ZiliangZiliang

Site navigation

  • Mortgage comparison
  • Japan tax calculator
  • Programming
  • Algorithms
  • Machine learning
  • Misc
Engineering
Contact
中文

Site navigation

  • Mortgage comparison
  • Japan tax calculator
  • Programming
  • Algorithms
  • Machine learning
  • Misc
Engineering
Contact

Article directory

  • Programming Languages

    • Overview
    • Basics
    • Collections
    • Flow Control Statements
    • Function
    • Libraries and Modules
    • IO, File, and OS
    • Errors and Exceptions
    • Object-Oriented Design
    • Namespaces and Scopes
  • Data Structures and Algorithms

    • Overview
    • Math Formula
    • Math Code
    • Misc
    • String
    • Tree Traversal
    • Balanced Binary Trees
    • Heap
    • Segment Tree
    • Dynamic Programming
    • Tree Misc
    • Java
    • Disjoint Sets
    • Graph Traversal
    • Minimum Spanning Tree
    • Single-Source Shortest Paths
    • Strongly Connected Components
    • Cut Vertices and Bridges
    • Cache
    • Binary Search
    • Quicksort
    • Knapsack Problem
    • Vertex Cover Problem
    • Set Cover Problem
    • Principle Component Analysis
    • K-Center Problem

Strongly Connected Components

American computer scientist and mathematician Robert Tarjan is the discoverer of several graph algorithms, including Tarjan's off-line lowest common ancestors algorithm, and co-inventor of both splay trees and Fibonacci heaps. Here we show Tarjan's strongly connected components algorithm.

This algorithm only runs DFS once. For a graph represented by adjacency list, its worst-case time complexity is O(|V|+|E|)

Example

Graph

Adjacency List

  • 0: 1
  • 1: 3
  • 2: 1
  • 3: 2 -> 4
  • 4: 5
  • 5: 7
  • 6: 4
  • 7: 6

Tarjan's Algorithm

from typing import List
from collections import OrderedDict


def tarjan(graph: List[List[int]]) -> int:
    n = len(graph)
    dfn = {}
    low = {}
    tree = OrderedDict()
    step = 0
    ans = 0  # number of scc

    def dfs(u):
        nonlocal graph, dfn, low, tree, step, ans
        dfn[u] = step
        low[u] = step
        step += 1
        tree[u] = None
        for v in graph[u]:
            if v not in dfn:
                dfs(v)
                low[u] = min(low[u], low[v])
            elif v in tree:
                low[u] = min(low[u], dfn[v])
        if dfn[u] == low[u]:
            w = None
            while w != u:
                w, _ = tree.popitem()
                print(w, end=' ')
            print()
            ans += 1

    for u in range(n):
        if u not in dfn:
            dfs(u)

    return ans

Tests

Edit this page on GitHub
Last Updated: 9/10/26, 7:37 AM
Contributors: Lucien
Prev
Single-Source Shortest Paths
Next
Cut Vertices and Bridges