A directed graph is a graph where each edge has a start vertex and an end vertex.
- Only follow directed edges.
- explore(v) finds all vertices reachable from v.
- Can still compute pre- and post- orderings.
A cycle in a graph G is a sequence of vertices v1, v2, ..., vn so that (v1, v2), (v2, v3), ... , (vn-1, vn), (vn, v1) are all edges.
If G contains a cycle, it cannot be linearly ordered.
A directed graph G is a Directed Acyclic Graph (or DAG) if it has no cycles.
- Being a DAG is necessary to linearly order.
A source is a vertex with no incoming edges.
A sink is a vertex with on outgoing edges.
- Find sink
- Put at end of order
- Remove from graph
- Repeat
Follow path as far as possible.
v1 -> v2 -> ... ->vn. Eventually either.
- Cannot extend (found sink).
- Repeat a vertex (have a cycle).
LinearOrder(G)
while G non-empty:
Follow a path until cannot extend
Find sink v
Put v at end of order
Remove v from G
- O(|V|) paths.
- Each takes O(|V|) time.
- Runtime O(|V|^2)
- Retrace same path every time
- Instead only back up as far as necessary
TopologicalSort(G)
DFS(G)
sort vertices by reverse post-order
If G is a DAG, with an edge u to v, post(u) > post(v).
Two vertices v, w in a directed graph are connected if you can reach v from w and can reach w from v.
A directed graph can be partitioned into strongly connected components where two vertices are connected if and only if they are in the same component.
We can also draw a metagraph showing how the strongly connected components connect to one another.
Example
Note: It's a DAG.
The metagraph of a graph G is always a DAG.
input: A directed graph
output: The strongly connected components of G.
EasySCC(G)
for each vertex v:
run explore(v) to determine vertices reachable from v
for each vertex v:
find the u reachable from v that can also reach v
these are the SCCs
O(|V|^2 + |V||E|). Want faster.
Idea: If v is in a sink SCC, explore(v) finds vertices reachable from v. This is exactly the SCC of v.
Need a way to find a sink SCC.
If C and C' are two strongly connected components with an edge from some vertex of C to some vertex of C', then largest post number in C bigger than the largest post number in C'.
Conclusion: The vertex with the largest postorder number is in a source component!
Let G^R be the graph obtained from G by revesing all of the edges.
- G^R and G have same SCCs.
- Source components of G^R are sink components of G.
FInd sink components of G by running DFS on G^R
Note: The vertex with the largest postorder number in G^R is in a sink SCC of G.
SCCs(G)
run DFS(G^R)
let v have largest post number
run Explore(v)
vertices found are first SCC
Remove from G and repeat
- Don't need to rerun DFS on G^R.
- Largest remaining post number comes from sink component.
SCCs(G)
run DFS(G^R)
for v ∈ V in reverse postorder:
if not visited(v):
Explore(v)
mark visited vertices as new SCC
- Essentially DFS on R^G and then on G.
- Runtime O(|V| + |E|)