Graph Algorithms
Graph Algorithms
3 novembre 2021
Graphs
A graph G = (V , E ) is
I V = set of vertices
I E = set of edges = subset of V × V
Undirected graphs
In an undirected graph :
I Edge (u, v ) = edge (v , u)
I No self-loops
In the graph below, (2, 1) = (1, 2)
There is no edge (self-loop) such as (i, i)
Directed graphs
In a directed graph :
I Edge (u,v) goes from vertex u to vertex v, notated u → v
In the graph below, there is an edge (1 → 2) but no edge (2 → 1),
thus edge (u, v ) 6= edge (v , u)
Connected graphs
A connected graph has a path from every node to every other
I believe the graph in Figure 1 is connected
The graph in Figure 2 is definitely not connected, there is no path
from node 0 to node 1.
Figure – 1
Figure – 2
Weighted graphs
Example :
Graphs : Adjacency Matrix
Example :
A 1 2 3 4
1 a d
2 b
3
4 c
Graphs : Adjacency Matrix
I Using an adjacency matrix, an n × n array is needed to store it, so
it has a O(V 2 ) space requirement
I The maximum amount of storage needed by an adjacency matrix
representation of an undirected graph with 4 vertices is 6 bits in
unweighted graphs, 6 integers for weighted graphs. This is
because
I Undirected graph implies that the matrix is symmetric
I No self-loops, therefore don’t need diagonal
1 2 3 4
1 1 1
2 1
3 1
4
Graphs : Adjacency Matrix
For each vertex v ∈ V , stores the vertices adjacent to v in the link list
pointed to by Adj[v ] (see example below)
Example :
I Adj[1] = {2,3}
I Adj[2] = {3}
I Adj[3] = {}
I Adj[4] = {3}
Variation : can also keep a list of
edges coming into vertex
Graphs : Adjacency List
BFS(G, s)
for each u ∈ G .V − {s}
u.color = WHITE
u.d = ∞ ; /* u.d is distance from source s to u */
u.π = NIL /* u.π is the predecessor of u */
s.color = GRAY
s.d = 0 ; s.π = NIL
Q=∅
Enqueue(Q,s)
while (Q not empty)
u = Dequeue(Q)
for each v ∈ u.adj
if (v.color == WHITE)
v.color = GREY
v.d = u.d + 1
v.π = u
Enqueue(Q, v) ;
u.color = BLACK ;
Breadth-First Search : Algorithm
BFS(G, s)
for each u ∈ G .V − {s} I Initialisation phase takes O(V )
u.color = WHITE I while iterates V times
u.d = ∞ ; u.π = NIL
s.color = GRAY
I In the worst case the inner for loop
s.d = 0 ; s.π = NIL can run V − 1 times, thus in O(V )
Q=∅ I So O(V 2 ) for the while loop in
Enqueue(Q,s) worst case
while (Q not empty)
u = Dequeue(Q)
for each v ∈ u.adj
if (v.color == WHITE)
v.color = GREY
v.d = u.d + 1
v.π = u
Enqueue(Q, v) ;
u.color = BLACK ;
BFS : aggregate analysis
Assuming the inner for loop in the while loop is our basic operation, how many
P
time this for can be executed ? k∈V deg (k) = 2|E |
BFS(G, s)
for each k ∈ G .V − {s} s= {r,w}
k.color = WHITE r= {v,s}
k.d = ∞ ; k.π = NIL w= {s,t,x}
s.color = GRAY v= {y}
s.d = 0 ; s.π = NIL t= {w,x,u}
Q=∅ x= {w,y,t}
Enqueue(Q,s) u= {t,y}
while (Q not empty) y= {x,u}
k = Dequeue(Q)
Iteration 1, k = s, v = {r , w }
for each v ∈ k.adj
Iteration 2 k = r , v = {v , s}
if (v.color == WHITE)
Iteration 3 k = w , v = {s, t, x}
v.color = GREY
Iteration 4 k = v , v = {y }
v.d = k.d + 1
Iteration 5 k = t, v = {w , x, u}
v.π = k
Iteration 6 k = x, v = {w , y , t}
Enqueue(Q, v) ;
Iteration 7 k = y , v = {t, y }
u.color = BLACK ;
Iteration 8 k = u, v = {x, u}
BFS : aggregate analysis
In one iteration k of the while loop, each iteration of the for loop copy in the queue
Q one white node from the adjacency list of node k
BFS(G, s)
for each k ∈ G .V − {s} s= {r,w}
k.color = WHITE r= {v,s}
k.d = ∞ ; k.π = NIL w= {s,t,x}
s.color = GRAY v= {y}
s.d = 0 ; s.π = NIL t= {w,x,u}
Q=∅ x= {w,y,t}
Enqueue(Q,s) u= {t,y}
while (Q not empty) y= {x,u}
k = Dequeue(Q)
Iteration 0 of the while loop Q = {s}
for each v ∈ k.adj
Iteration 1, k = s, Q = {r , w }
if (v.color == WHITE)
Iteration 2 k = r , Q = {w , v }
v.color = GREY
Iteration 3 k = w , Q = {v , t, x}
v.d = k.d + 1
Iteration 4 k = v , Q = {t, x, y }
v.π = k
Iteration 5 k = t, Q = {x, y , u}
Enqueue(Q, v) ;
Iteration 6 k = x, Q = {y , u}
u.color = BLACK ;
Iteration 7 k = y , Q = {u}
Iteration 7 k = u, Q = {}
BFS : aggregate analysis
BFS(G, s)
for each u ∈ G .V − {s} I Actually, each edge is considered at most
u.color = WHITE one time for all the V iterations of the
u.d = ∞ ; u.π = NIL
inner for loop, so rather we use
s.color = GRAY
aggregate analysis :
s.d = 0 ; s.π = NIL
Q=∅ I rather than considering the worst
Enqueue(Q,s) case of the for loop, we consider
while (Q not empty) I the total number of iterations of the
u = Dequeue(Q) for loop over the V iterations of the
for each v ∈ u.adj
while loop
if (v.color == WHITE) I This total number cannot exceed E
v.color = GREY
v.d = u.d + 1 as each edge is considered at most
v.π = u once
Enqueue(Q, v) ; I Total running time : O(V + E )
u.color = BLACK ;
Breadth-First Search & shortest path
In an unweighted, undirected grah, BFS calculates the shortest-path
distance to the source vertex
I Shortest-path distance δ(s, v ) = minimum number of edges from
s to v , or ∞ if v not reachable from s
I BFS builds breadth-first tree, in which paths to root represent
shortest paths in G
I Thus can use BFS to calculate shortest path from one vertex to
the others in the graph in O(V + E ) time
Depth-First Search
u.d = time node u is first visited ; u.f = time when the exploration of
the node u is completed
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
DFS : Example
DFS Visit(u)
u.color = GREY ;
time = time+1 ;
u.d = time ;
for each v ∈ u.Adj[]
if (v.color == WHITE)
DFS Visit(v) ;
u.color = BLACK ;
time = time+1 ;
u.f = time ;
Aggregate analysis of DFS
I The two for loops in DFS(G) each takes Θ(V )
I The procedure DFS visit is called exactly once for each vertex
v ∈V
I The for loop in DFS visit is executed |u.adj[]| times
I Since v ∈V |u.adj[]| = Θ(E ), the total cost of DFS visit is Θ(E )
P
Theorem 22.10 :
If G is undirected, a DFS produces only tree and back edges
Topological-Sort()
I Run DFS
I When a vertex u is finished (i.e. when u.f is assigned a time
value), output it
Vertices are output in reverse topological order. Time : O(V + E )
Topological Sort
Figure – 1
11. Using the graph of Figure 1 and the tree you obtained in the
previous question, identify in Figure 1 the edges that are tree
edges, back edges and forward edges
12. Does the graph in Figure 1 is an acyclic graph ? Explain briefly
your answer.
13. Rewrite the DFS algorithm on slide 36, using a stack to eliminate
recursion
Exercises
374 414
311 373
143 351 352
332
312 344 417
331 333
341 140 413
410
403 142
154 415