\(\)
\(%\newcommand{\CLRS}{\href{https://mitpress.mit.edu/books/introduction-algorithms}{Cormen et al}}\)
\(\newcommand{\CLRS}{\href{https://mitpress.mit.edu/books/introduction-algorithms}{Introduction to Algorithms, 3rd ed.} (\href{http://libproxy.aalto.fi/login?url=http://site.ebrary.com/lib/aalto/Doc?id=10397652}{online via Aalto lib})}\)
\(\newcommand{\SW}{\href{http://algs4.cs.princeton.edu/home/}{Algorithms, 4th ed.}}\)
\(%\newcommand{\SW}{\href{http://algs4.cs.princeton.edu/home/}{Sedgewick and Wayne}}\)
\(\)
\(\newcommand{\Java}{\href{http://java.com/en/}{Java}}\)
\(\newcommand{\Python}{\href{https://www.python.org/}{Python}}\)
\(\newcommand{\CPP}{\href{http://www.cplusplus.com/}{C++}}\)
\(\newcommand{\ST}[1]{{\Blue{\textsf{#1}}}}\)
\(\newcommand{\PseudoCode}[1]{{\color{blue}\textsf{#1}}}\)
\(\)
\(%\newcommand{\subheading}[1]{\textbf{\large\color{aaltodgreen}#1}}\)
\(\newcommand{\subheading}[1]{\large{\usebeamercolor[fg]{frametitle} #1}}\)
\(\)
\(\newcommand{\Blue}[1]{{\color{flagblue}#1}}\)
\(\newcommand{\Red}[1]{{\color{aaltored}#1}}\)
\(\newcommand{\Emph}[1]{\emph{\color{flagblue}#1}}\)
\(\)
\(\newcommand{\Engl}[1]{({\em engl.}\ #1)}\)
\(\)
\(\newcommand{\Pointer}{\raisebox{-1ex}{\huge\ding{43}}\ }\)
\(\)
\(\newcommand{\Set}[1]{\{#1\}}\)
\(\newcommand{\Setdef}[2]{\{{#1}\mid{#2}\}}\)
\(\newcommand{\PSet}[1]{\mathcal{P}(#1)}\)
\(\newcommand{\Card}[1]{{\vert{#1}\vert}}\)
\(\newcommand{\Tuple}[1]{(#1)}\)
\(\newcommand{\Implies}{\Rightarrow}\)
\(\newcommand{\Reals}{\mathbb{R}}\)
\(\newcommand{\Seq}[1]{(#1)}\)
\(\newcommand{\Arr}[1]{[#1]}\)
\(\newcommand{\Floor}[1]{{\lfloor{#1}\rfloor}}\)
\(\newcommand{\Ceil}[1]{{\lceil{#1}\rceil}}\)
\(\newcommand{\Path}[1]{(#1)}\)
\(\)
\(%\newcommand{\Lg}{\lg}\)
\(\newcommand{\Lg}{\log_2}\)
\(\)
\(\newcommand{\BigOh}{O}\)
\(%\newcommand{\BigOh}{\mathcal{O}}\)
\(\newcommand{\Oh}[1]{\BigOh(#1)}\)
\(\)
\(\newcommand{\todo}[1]{\Red{\textbf{TO DO: #1}}}\)
\(\)
\(\newcommand{\NULL}{\textsf{null}}\)
\(\)
\(\newcommand{\Insert}{\ensuremath{\textsc{insert}}}\)
\(\newcommand{\Search}{\ensuremath{\textsc{search}}}\)
\(\newcommand{\Delete}{\ensuremath{\textsc{delete}}}\)
\(\newcommand{\Remove}{\ensuremath{\textsc{remove}}}\)
\(\)
\(\newcommand{\Parent}[1]{\mathop{parent}(#1)}\)
\(\)
\(\newcommand{\ALengthOf}[1]{{#1}.\textit{length}}\)
\(\)
\(\newcommand{\TRootOf}[1]{{#1}.\textit{root}}\)
\(\newcommand{\TLChildOf}[1]{{#1}.\textit{leftChild}}\)
\(\newcommand{\TRChildOf}[1]{{#1}.\textit{rightChild}}\)
\(\newcommand{\TNode}{x}\)
\(\newcommand{\TNodeI}{y}\)
\(\newcommand{\TKeyOf}[1]{{#1}.\textit{key}}\)
\(\)
\(\newcommand{\PEnqueue}[2]{{#1}.\textsf{enqueue}(#2)}\)
\(\newcommand{\PDequeue}[1]{{#1}.\textsf{dequeue}()}\)
\(\)
\(\newcommand{\Def}{\mathrel{:=}}\)
\(\)
\(\newcommand{\Eq}{\mathrel{=}}\)
\(\newcommand{\Asgn}{\mathrel{\leftarrow}}\)
\(%\newcommand{\Asgn}{\mathrel{:=}}\)
\(\)
\(%\)
\(% Heaps\)
\(%\)
\(\newcommand{\Downheap}{\textsc{downheap}}\)
\(\newcommand{\Upheap}{\textsc{upheap}}\)
\(\newcommand{\Makeheap}{\textsc{makeheap}}\)
\(\)
\(%\)
\(% Dynamic sets\)
\(%\)
\(\newcommand{\SInsert}[1]{\textsc{insert}(#1)}\)
\(\newcommand{\SSearch}[1]{\textsc{search}(#1)}\)
\(\newcommand{\SDelete}[1]{\textsc{delete}(#1)}\)
\(\newcommand{\SMin}{\textsc{min}()}\)
\(\newcommand{\SMax}{\textsc{max}()}\)
\(\newcommand{\SPredecessor}[1]{\textsc{predecessor}(#1)}\)
\(\newcommand{\SSuccessor}[1]{\textsc{successor}(#1)}\)
\(\)
\(%\)
\(% Union-find\)
\(%\)
\(\newcommand{\UFMS}[1]{\textsc{make-set}(#1)}\)
\(\newcommand{\UFFS}[1]{\textsc{find-set}(#1)}\)
\(\newcommand{\UFCompress}[1]{\textsc{find-and-compress}(#1)}\)
\(\newcommand{\UFUnion}[2]{\textsc{union}(#1,#2)}\)
\(\)
\(\)
\(%\)
\(% Graphs\)
\(%\)
\(\newcommand{\Verts}{V}\)
\(\newcommand{\Vtx}{v}\)
\(\newcommand{\VtxA}{v_1}\)
\(\newcommand{\VtxB}{v_2}\)
\(\newcommand{\VertsA}{V_\textup{A}}\)
\(\newcommand{\VertsB}{V_\textup{B}}\)
\(\newcommand{\Edges}{E}\)
\(\newcommand{\Edge}{e}\)
\(\newcommand{\NofV}{\Card{V}}\)
\(\newcommand{\NofE}{\Card{E}}\)
\(\newcommand{\Graph}{G}\)
\(\)
\(\newcommand{\SCC}{C}\)
\(\newcommand{\GraphSCC}{G^\text{SCC}}\)
\(\newcommand{\VertsSCC}{V^\text{SCC}}\)
\(\newcommand{\EdgesSCC}{E^\text{SCC}}\)
\(\)
\(\newcommand{\GraphT}{G^\text{T}}\)
\(%\newcommand{\VertsT}{V^\textup{T}}\)
\(\newcommand{\EdgesT}{E^\text{T}}\)
\(\)
\(%\)
\(% NP-completeness etc\)
\(%\)
\(\newcommand{\Poly}{\textbf{P}}\)
\(\newcommand{\NP}{\textbf{NP}}\)
\(\newcommand{\PSPACE}{\textbf{PSPACE}}\)
\(\newcommand{\EXPTIME}{\textbf{EXPTIME}}\)
Strongly Connected Components
Finding the strongly connected components of a directed graph is
another algorithm based on Depth-first search.
For a directed graph \( \Graph = \Tuple{\Verts,\Edges} \),
a strongly connected component, or simply an SCC,
is a maximal subset \( \SCC \subseteq \Verts \) such that
for all the vertices \( u,v \in \SCC \),
it holds that \( v \) is reachable from \( u \) and \( u \) is reachable from \( v \).
Thus each cycle in a directed graph is inside an SCC.
Vertices that are not in any cycle form their own unit components.
Example
Consider the graph shown below.
Its strongly connected components,
shown with the red areas,
are \( \Set{s} \), \( \Set{t,u} \), \( \Set{v} \), and \( \Set{w,x,y,z} \).
The component graph \( \GraphSCC = \Tuple{\VertsSCC,\EdgesSCC} \) of
a directed graph \( \Graph \) is the directed graph where
the vertices \( \VertsSCC \) are the connected components of \( \Graph \),
and
there is an edge
\( \Tuple{\SCC,\SCC’} \in \VertsSCC \)
from a component vertex \( \SCC \) to
a different component vertex \( \SCC’ \) if
\( \Tuple{u,v} \) is an edge in \( \Graph \)
for some \( u \in \SCC \) and \( v \in \SCC’ \).
The component graph is acyclic. Why?
Example
Consider again the graph shown in the previous example.
Its component graph is shown below.
There are several linear time,
meaning \( \Oh{\Card{V}+\Card{E}} \) in this context,
algorithms for computing the SCCs of a directed graph \( \Graph = \Tuple{\Verts,\Edges} \),
see e.g. this Wikipedia article.
The following presents a variant of Kosaraju’s algorithm.
It uses depth-first search twice:
Perform depth-first search on the original graph to obtain the visit time-stamps.
Make the transpose \( \GraphT \) of the graph \( \Graph = \Tuple{\Verts,\Edges} \) by reversing the directions of the edges:
\( \GraphT = \Tuple{\Verts, \EdgesT} \),
where \( \EdgesT = \Setdef{\Tuple{u,v}}{\Tuple{v,u} \in \Edges} \).
Perform depth-first search on the transpose graph \( \GraphT \)
but start the sub-searches from the vertices in
the reverse order of the finish time-stamps produced by the
first depth-first search.
The SCCs are the nodes in the depth-first search forests produced by
the second depth-first search.
Example
Consider the graph drawn below.
Its strongly connected components are
\( \Set{s} \), \( \Set{t,u} \), \( \Set{v} \), and \( \Set{w,x,y,z} \).
Also shown in the graph are the time-stamps and the tree edges
obtained by performing a depth-first search on the graph.
The transpose of the graph above is shown below.
Observe that the SCCs of the transpose are the same as those of the original graph.
Similarly, the component graph is again a DAG but transposed.
The graph below shows the result of applying
depth-first search on the transpose graph
in the reverse order of the finish time-stamps of the first depth-first search.
The sub-search starting from \( t \) finds the “leaf component” \( \Set{t,u} \)
The sub-search from \( v \) discovers the unit component \( \Set{v} \)
The sub-search from \( s \) discovers the unit component \( \Set{s} \)
The sub-search from \( z \) discovers the “root component” \( \Set{w,x,y,z} \)
The same graph but drawn in a different order in order to illustrate
the order in which the components are found:
Why does this algorithm work?
Below is a rough sketch, a more complete proof can be found in the book Introduction to Algorithms, 3rd ed. (online via Aalto lib).
The first depth-first search gives, in the finish time-stamps,
a reverse topological sorting for the SCCs
in the component graph.
The component graph of the transpose graph is
the transpose of the component graph of the original graph.
Performing the second depth-first search on the transpose graph
in the reverse topological order given by the first depth-first search
first finds a component that does not have any successors in the transpose component graph,
then finds a component that does not have any successors or
whose successors have already been found in the transpose component graph,
and so on.