1 of 125

Graph Algorithms I

Summer 2018 • Lecture 07/19

2 of 125

Outline for Today

Graph algorithms

Graph Basics

DFS: topological sort, in-order traversal of BSTs, exact traversals

BFS: shortest paths, bipartite graph detection

Kosaraju’s Algorithm for SCC’s

3 of 125

Graph Basics

4 of 125

Examples of Graphs

The Internet (circa 1999)

5 of 125

Examples of Graphs

Flight networks (Jet Blue, for example)

6 of 125

Examples of Graphs

Neural networks

7 of 125

Graphs

We might want to answer one of several questions about G.

Finding the shortest path between two vertices (SPSP) for efficient routing.

Finding strongly connected components for community detection or clustering.

Finding the topological ordering to respect dependencies.

8 of 125

Undirected Graphs

An undirected graph has vertices and edges.

V is the set of vertices and E is the set of edges.

Formally, an undirected graph is G = (V, E).

e.g. V = {A, B, C, D} and E = { {A, B}, {A, C}, {A, D}, {B, C}, {C, D} }

D

B

A

C

9 of 125

Directed Graphs

A directed graph has vertices and directed edges.

V is the set of vertices and E is the set of directed edges.

Formally, a directed graph is G = (V, E)

e.g. V = {A, B, C, D} and E = { [A, B], [A, D], [B, C], [C, A], [D, A], [D, C] }

D

B

A

C

10 of 125

Graph Representations

How do we represent graphs?

(1) Adjacency matrix

D

B

A

C

A

B

C

D

A B C D

0 1 1 1

1 0 1 0

1 1 0 1

1 0 1 0

11 of 125

Graph Representations

How do we represent graphs?

(1) Adjacency matrix

A

B

C

D

A B C D

D

B

A

C

source

destination

0 1 0 1

0 0 1 0

1 0 0 0

1 0 1 0

12 of 125

Graph Representations

How do we represent graphs?

(1) Adjacency matrix

(2) Adjacency list

D

B

A

C

A B C D

B

D

C

A

A

C

13 of 125

Graph Representations

For G = (V, E)

O(deg(u))

or

O(deg(v))

O(1)

Edge Membership

Is e = {u, v} in E?

0 1 0 1

0 0 1 0

1 0 0 0

1 0 1 0

O(deg(v))

O(|V|)

Neighbor Query

What are the neighbors of u?

O(|V|+|E|)

O(|V|2)

Space requirements

Generally, better for sparse graphs.

We’ll assume this representation, unless otherwise stated.

14 of 125

Depth-First Search

15 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

16 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

17 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

18 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

19 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

20 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

21 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

22 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

23 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

24 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

25 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

26 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

27 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

28 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

29 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

30 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

31 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

32 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

33 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

34 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

35 of 125

An analogy

A smart bunny exploring a labyrinth with chalk (to mark visited destinations)

and thread (to retrace steps).

Depth-First Search

s

unvisited

visited, but not fully explored

visited, and fully explored

36 of 125

Depth-First Search

def dfs(u, cur_time):

u.start_time = cur_time

cur_time += 1

u.status = "in_progress"

for v in u.neighbors:

if v.status is "unvisited":

cur_time = dfs(v, cur_time)

cur_time += 1

u.end_time = cur_time

u.status = "done"

return cur_time

Runtime: O(|V|+|E|)

37 of 125

Depth-First Search

s

start_time: 0

38 of 125

Depth-First Search

s

start_time: 0

start_time: 1

end_time: 12

39 of 125

Depth-First Search

s

start_time: 0

start_time: 1

end_time: 12

st: 4

et: 5

st: 3

et: 8

st: 6

et: 7

st: 2

et: 11

st: 9

et: 10

40 of 125

Depth-First Search

s

start_time: 0

start_time: 1

end_time: 12

st: 4

et: 5

st: 3

et: 8

st: 6

et: 7

st: 2

et: 11

st: 9

et: 10

41 of 125

Depth-First Search

s

start_time: 0

start_time: 1

end_time: 12

st: 4

et: 5

st: 3

et: 8

st: 6

et: 7

st: 2

et: 11

st: 9

et: 10

42 of 125

Depth-First Search

s

start_time: 0

start_time: 1

end_time: 12

st: 4

et: 5

st: 3

et: 8

st: 6

et: 7

st: 2

et: 11

st: 9

et: 10

start_time: 13

start_time: 14

43 of 125

Depth-First Search

s

start_time: 0

start_time: 1

end_time: 12

st: 4

et: 5

st: 3

et: 8

st: 6

et: 7

st: 2

et: 11

st: 9

et: 10

start_time: 13

end_time: 14

44 of 125

Depth-First Search

s

start_time: 0

end_time: 15

start_time: 1

end_time: 12

st: 4

et: 5

st: 3

et: 8

st: 6

et: 7

st: 2

et: 11

st: 9

et: 10

start_time: 13

end_time: 14

45 of 125

Depth-First Search

DFS finds all vertices reachable from the starting point, called a connected component.

DFS works fine on directed graphs as well.

e.g. From u, only visit v1 not v2.

u

v1

v2

46 of 125

Topological Ordering

47 of 125

Aside: Directed Acyclic Graphs

A dependency graph is an instantiation of a directed acyclic graph (DAG) i.e. a directed graph with no directed cycles.

Which of these graphs are valid DAGs?

48 of 125

Aside: Directed Acyclic Graphs

A dependency graph is an instantiation of a directed acyclic graph (DAG) i.e. a directed graph with no directed cycles.

Which of these graphs are valid DAGs?

49 of 125

Topological Ordering

Application of DFS: Given a package dependency graph, in what order should packages be installed?

DFS produces a topological ordering, which solves this problem.

Definition: The topological ordering of a DAG is an ordering of its vertices

such that for every directed edge (u, v) E, u precedes v in the ordering.

50 of 125

Topological Ordering

Application of DFS: Given a package dependency graph, in what order should packages be installed?

DFS produces a topological ordering, which solves this problem.

Definition: The topological ordering of a DAG is an ordering of its vertices

such that for every directed edge (u, v) E, u precedes v in the ordering.

mongoose

async

mongodb

bluebird

nyc

bson

rimraf

A

B

means A depends on B i.e. install B before A.

Sometimes it’s possible to topologically order the vertices by hand.

51 of 125

Topological Ordering

Application of DFS: Given a package dependency graph, in what order should packages be installed?

DFS produces a topological ordering, which solves this problem.

Definition: The topological ordering of a DAG is an ordering of its vertices

such that for every directed edge (u, v) E, u precedes v in the ordering.

Sometimes it’s not …

52 of 125

Topological Ordering

Claim: If (u, v) E, then end_time of u > end_time of v.

Intuition: dfs visits and finishes with all of the neighbors

of u before finishing u itself. Also, a DAG does not have

cycles, so dfs will never traverse to an in-progress vertex

(only unvisited and done vertices).

53 of 125

Topological Ordering

def dfs(u, cur_time):

u.start_time = cur_time

cur_time += 1

u.status = "in_progress"

for v in u.neighbors:

if v.status is "unvisited":

cur_time = dfs(v, cur_time)

cur_time += 1

u.end_time = cur_time

u.status = "done"

return cur_time

Runtime: O(|V|+|E|)

54 of 125

Topological Ordering

reversed_topological_list = []

def dfs(u, cur_time):

u.start_time = cur_time

cur_time += 1

u.status = "in_progress"

for v in u.neighbors:

if v.status is "unvisited":

cur_time = dfs(v, cur_time)

cur_time += 1

u.end_time = cur_time

u.status = "done"

reversed_topological_list.append(u)

return cur_time

Runtime: O(|V|+|E|)

55 of 125

Topological Ordering

For the package dependency graph, packages should be installed in reverse topological order, so we can just return reversed_topological_list.

To compute the topological ordering in general, reverse the order of reversed_topological_list.

e.g. Finding an order to take courses that satisfies prerequisites.

106A

106B

107

108

103

109

110

161

142

56 of 125

In-Order Traversal of BSTs

Application of DFS: Given a BST, output the vertices in order.

5

3

6

2

4

7

1

57 of 125

Exact Traversals of Graphs

Application of DFS: Find an exact traversal, a path that touches all vertices exactly once.

Suppose I deliver pizzas in SF. My route has 6 stops but since I bike and the

terrain is hilly, I can only bike from one stop to another in one direction. Can

I plan the most efficient route that visits each destination once?

58 of 125

Breadth-First Search

59 of 125

An analogy

A bird exploring a labyrinth from above (with a bird’s eye view).

Breadth-First Search

s

unvisited

reachable in

0 steps

reachable in

1 steps

reachable in

2 steps

reachable in

3 steps

60 of 125

An analogy

A bird exploring a labyrinth from above (with a bird’s eye view).

Breadth-First Search

s

unvisited

reachable in

0 steps

reachable in

1 steps

reachable in

2 steps

reachable in

3 steps

61 of 125

An analogy

A bird exploring a labyrinth from above (with a bird’s eye view).

Breadth-First Search

s

unvisited

reachable in

0 steps

reachable in

1 steps

reachable in

2 steps

reachable in

3 steps

62 of 125

An analogy

A bird exploring a labyrinth from above (with a bird’s eye view).

Breadth-First Search

s

unvisited

reachable in

0 steps

reachable in

1 steps

reachable in

2 steps

reachable in

3 steps

63 of 125

Breadth-First Search

def bfs(s):

L = []

for i = 0 to n-1:

L[i] = {}

L[0] = {s}

for i = 0 to n-1:

for u in L[i]:

for v in u.neighbors:

if v.status is "unvisited":

v.status = "visited"

L[i+1].add(v)

Runtime: O(|V|+|E|)

64 of 125

Shortest Path

Application of BFS: How long is the shortest path between

vertices u and v?

Call bfs(u).

For all vertices in L[i], the shortest path between u and these vertices has

length i.

If v isn’t in L[i] for any i, then it’s unreachable from u.

65 of 125

Aside: Bipartiteness

A graph is bipartite iff there exists a two-coloring such that there are no edges between same-colored vertices.

e.g. Matching university hackathon guests and hosts.

66 of 125

Shortest Path

Application of BFS: Is a graph bipartite?

Call bfs from any vertex and color vertices alternating colors.

If it attempts to color the same vertex different colors, then the graph isn’t

bipartite; otherwise it is.

s

67 of 125

Shortest Path

Application of BFS: Is a graph bipartite?

Call bfs from any vertex and color vertices alternating colors.

If it attempts to color the same vertex different colors, then the graph isn’t

bipartite; otherwise it is.

s

68 of 125

Shortest Path

Application of BFS: Is a graph bipartite?

Call bfs from any vertex and color vertices alternating colors.

If it attempts to color the same vertex different colors, then the graph isn’t

bipartite; otherwise it is.

s

69 of 125

Shortest Path

Application of BFS: Is a graph bipartite?

Call bfs from any vertex and color vertices alternating colors.

If it attempts to color the same vertex different colors, then the graph isn’t

bipartite; otherwise it is.

s

BIPARTITE!

70 of 125

Shortest Path

Application of BFS: Is a graph bipartite?

Call bfs from any vertex and color vertices alternating colors.

If it attempts to color the same vertex different colors, then the graph isn’t

bipartite; otherwise it is.

s

71 of 125

Shortest Path

Application of BFS: Is a graph bipartite?

Call bfs from any vertex and color vertices alternating colors.

If it attempts to color the same vertex different colors, then the graph isn’t

bipartite; otherwise it is.

s

72 of 125

Shortest Path

Application of BFS: Is a graph bipartite?

Call bfs from any vertex and color vertices alternating colors.

If it attempts to color the same vertex different colors, then the graph isn’t

bipartite; otherwise it is.

s

73 of 125

Shortest Path

Application of BFS: Is a graph bipartite?

Call bfs from any vertex and color vertices alternating colors.

If it attempts to color the same vertex different colors, then the graph isn’t

bipartite; otherwise it is.

s

NOT BIPARTITE!

74 of 125

Shortest Path

Application of BFS: Is a graph bipartite?

Call bfs from any vertex and color vertices alternating colors.

If it attempts to color the same vertex different colors, then the graph isn’t

bipartite; otherwise it is.

Is anyone incredulous that this actually works?

s

NOT BIPARTITE!

75 of 125

Shortest Path

There exist many poor colorings on legitimate bipartite graphs.

Just because this coloring that doesn’t work, why does that mean that

no coloring works?

This is a poor coloring on an obviously bipartite graph.

76 of 125

Shortest Path

Theorem: bfs colors two neighbors the same color iff the graph is not bipartite.

Proof:

Since bfs colors vertices alternating colors, it colors two neighbors the same

color iff it’s found a cycle of odd length in the graph. Therefore, the graph

contains an odd cycle as a subgraph. But it’s impossible to color an odd cycle

with two colors such that no two neighbors have the same color. Therefore,

it’s impossible to two-color the graph such that the no edges between

same-colored vertices, and the graph must not be bipartite.

77 of 125

3 min break

78 of 125

A directed graph G = (V, E) is strongly connected if,

for all pairs of vertices u and v, there’s a path from u to v

and a path from v to u.

Strongly Connected Components

79 of 125

A directed graph G = (V, E) is strongly connected if,

for all pairs of vertices u and v, there’s a path from u to v

and a path from v to u.

Strongly Connected Components

80 of 125

We can decompose a graph into its strongly connected components (SCCs).

Strongly Connected Components

81 of 125

Why do we care about SCCs?

SCCs provide information about communities.

A computer scientist might want to decompose the Internet into SCCs

to find related topics.

An economist might want to decompose labor market data into SCCs

before making sense of it.

A football executive might want to determine which Pac-12 school should

play in the Rose Bowl.

Strongly Connected Components

82 of 125

How many SCCs are in this graph?

Strongly Connected Components

83 of 125

Strongly Connected Components

How many SCCs are in this graph? 3; let’s find them!

84 of 125

1. Repeat dfs from an arbitrary vertex until done.

Kosaraju’s Algorithm

85 of 125

1. Repeat dfs from an arbitrary vertex until done.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

86 of 125

1. Repeat dfs from an arbitrary vertex until done.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

87 of 125

1. Repeat dfs from an arbitrary vertex until done.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

88 of 125

1. Repeat dfs from an arbitrary vertex until done.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

89 of 125

1. Repeat dfs from an arbitrary vertex until done.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

90 of 125

1. Repeat dfs from an arbitrary vertex until done.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

91 of 125

1. Repeat dfs from an arbitrary vertex until done.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

92 of 125

1. Repeat dfs from an arbitrary vertex until done.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

93 of 125

1. Repeat dfs from an arbitrary vertex until done.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

94 of 125

1. Repeat dfs from an arbitrary vertex until done.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

95 of 125

2. Reverse all of the edges.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

96 of 125

3. Repeat dfs again, starting with vertices with the largest end_time.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

97 of 125

3. Repeat dfs again, starting with vertices with the largest end_time.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

98 of 125

3. Repeat dfs again, starting with vertices with the largest end_time.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

This is one SCC.

99 of 125

3. Repeat dfs again, starting with vertices with the largest end_time.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

This is one SCC.

100 of 125

3. Repeat dfs again, starting with vertices with the largest end_time.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

This is one SCC.

101 of 125

3. Repeat dfs again, starting with vertices with the largest end_time.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

This is one SCC.

102 of 125

3. Repeat dfs again, starting with vertices with the largest end_time.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

This is one SCC.

103 of 125

3. Repeat dfs again, starting with vertices with the largest end_time.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

This is one SCC.

104 of 125

3. Repeat dfs again, starting with vertices with the largest end_time.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

This is one SCC.

105 of 125

3. Repeat dfs again, starting with vertices with the largest end_time.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

Here’s another SCC!

This is one SCC.

106 of 125

3. Repeat dfs again, starting with vertices with the largest end_time.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

Here’s another SCC!

This is one SCC.

107 of 125

3. Repeat dfs again, starting with vertices with the largest end_time.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

Here’s another SCC!

This is one SCC.

108 of 125

3. Repeat dfs again, starting with vertices with the largest end_time.

Kosaraju’s Algorithm

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 8

end_time: 9

This is one DFS tree.

Here’s the last one.

Here’s another SCC!

109 of 125

Whoa. How did that work?

Lemma 1: The SCC metagraph is a DAG.

Intuition: If not, then two SCCs would collapse into one.

Kosaraju’s Algorithm

110 of 125

Let the end time of a SCC be the largest end time of any element of that SCC.

Let the starting time of a SCC be the smallest starting time of any element of that SCC.

Kosaraju’s Algorithm

start_time: 2

end_time: 7

start_time: 3

end_time: 6

start_time: 4

end_time: 5

start_time: 0

end_time: 1

start_time: 2

end_time: 7

start_time: 8

end_time: 9

111 of 125

The main idea leverages the fact that vertex in the SCC metagraph with the largest end_time has no incoming

edges.

Kosaraju’s Algorithm

start_time: 8

end_time: 9

start_time: 2

end_time: 7

start_time: 0

end_time: 1

112 of 125

The main idea leverages the fact that vertex in the SCC metagraph with the largest end_time has no incoming

edges. After reversing the edges, it has no outgoing edges.

Kosaraju’s Algorithm

start_time: 8

end_time: 9

start_time: 2

end_time: 7

start_time: 0

end_time: 1

113 of 125

The main idea leverages the fact that vertex in the SCC metagraph with the largest end_time has no incoming

edges. After reversing the edges, it has no outgoing edges.

Running dfs on that vertex finds exactly that component.

Kosaraju’s Algorithm

start_time: 8

end_time: 9

start_time: 2

end_time: 7

start_time: 0

end_time: 1

114 of 125

The main idea leverages the fact that vertex in the SCC metagraph with the largest end_time has no incoming

edges. After reversing the edges, it has no outgoing edges.

Running dfs on that vertex finds exactly that component.

Same argument for the rest.

Kosaraju’s Algorithm

start_time: 8

end_time: 9

start_time: 2

end_time: 7

start_time: 0

end_time: 1

115 of 125

The main idea leverages the fact that vertex in the SCC metagraph with the largest end_time has no incoming

edges. After reversing the edges, it has no outgoing edges.

Running dfs on that vertex finds exactly that component.

Same argument for the rest.

Kosaraju’s Algorithm

start_time: 8

end_time: 9

start_time: 2

end_time: 7

start_time: 0

end_time: 1

116 of 125

The main idea leverages the fact that vertex in the SCC metagraph with the largest end_time has no incoming

edges. After reversing the edges, it has no outgoing edges.

Running dfs on that vertex finds exactly that component.

Same argument for the rest.

Kosaraju’s Algorithm

start_time: 8

end_time: 9

start_time: 2

end_time: 7

start_time: 0

end_time: 1

117 of 125

Claim: For each edge (u, v) in the SCC metagraph where u C1 and v C2, end_time of C1 must be larger than end_time of C2.

Kosaraju’s Algorithm

start_time: 8

end_time: 9

start_time: 2

end_time: 7

start_time: 0

end_time: 1

118 of 125

Claim: For each edge (u, v) in the SCC metagraph where u C1 and v C2, end_time of C1 must be larger than end_time of C2.

Kosaraju’s Algorithm

start_time: 8

end_time: 9

start_time: 2

end_time: 7

start_time: 0

end_time: 1

119 of 125

Claim: For each edge (u, v) in the SCC metagraph where u C1 and v C2, end_time of C1 must be larger than end_time of C2.

Kosaraju’s Algorithm

start_time: 8

end_time: 9

start_time: 2

end_time: 7

start_time: 0

end_time: 1

120 of 125

Claim: For each edge (u, v) in the SCC metagraph where u C1 and v C2, end_time of C1 must be larger than end_time of C2.

Kosaraju’s Algorithm

start_time: 8

end_time: 9

start_time: 2

end_time: 7

start_time: 0

end_time: 1

121 of 125

Claim: For each edge (u, v) in the SCC metagraph where u C1 and v C2, end_time of C1 must be larger than end_time of C2.

Kosaraju’s Algorithm

start_time: 2

end_time: 7

start_time: 0

end_time: 1

C2

C1

122 of 125

Claim: For each edge (u, v) in the SCC metagraph where u C1 and v C2, end_time of C1 must be larger than end_time of C2.

Intuition: In order for the end_time of C1 to be smaller than the end_time of

C2, all vertices in C1 must have end_times smaller than at least one end_time

of C2.

Kosaraju’s Algorithm

start_time: 2

end_time: 7

start_time: 0

end_time: 1

C2

C1

123 of 125

Claim: For each edge (u, v) in the SCC metagraph where u C1 and v C2, end_time of C1 must be larger than end_time of C2.

Intuition: In order for the end_time of C1 to be smaller than the end_time of

C2, all vertices in C1 must have end_times smaller than at least one end_time

of C2.

For this to occur, the first dfs must have marked all vertices in C1 as “done” before at least one vertex in C2.

Kosaraju’s Algorithm

start_time: 2

end_time: 7

start_time: 0

end_time: 1

C2

C1

124 of 125

Claim: For each edge (u, v) in the SCC metagraph where u C1 and v C2, end_time of C1 must be larger than end_time of C2.

Intuition: In order for the end_time of C1 to be smaller than the end_time of

C2, all vertices in C1 must have end_times smaller than at least one end_time

of C2.

For this to occur, the first dfs must have marked all vertices in C1 as “done” before at least one vertex in C2. But this is impossible since the first dfs must

have explored edge (u, v) before marking all vertices in C1 as “done.”

Kosaraju’s Algorithm

start_time: 2

end_time: 7

start_time: 0

end_time: 1

C2

C1

125 of 125

Claim: For each edge (u, v) in the SCC metagraph where u C1 and v C2, end_time of C1 must be larger than end_time of C2.

Intuition: In order for the end_time of C1 to be smaller than the end_time of

C2, all vertices in C1 must have end_times smaller than at least one end_time

of C2.

For this to occur, the first dfs must have marked all vertices in C1 as “done” before at least one vertex in C2. But this is impossible since the first dfs must

have explored edge (u, v) before marking all vertices in C1 as “done.” Since C2

is an SCC, all vertices in it are reachable from v; therefore, all must have an end_time smaller than u.

Kosaraju’s Algorithm

start_time: 2

end_time: 7

start_time: 0

end_time: 1

C2

C1