Lecture 3
DFS
1
Depth-First Search
● Input: 1 2
■ G = (V, E) (No source vertex given!) 3
● Goal: 5 4
■ Explore the edges of G to “discover” every vertex in V starting at the most
current visited node
■ Search may be repeated from multiple sources
● Output:
■ 2 timestamps on each vertex:
○ d[v] = discovery time
○ f[v] = finishing time (done with examining v’s adjacency list)
■ Depth-first forest
Depth-First Search
● Search “deeper” in the graph whenever possible 1 2
● Edges are explored out of the most recently 3
discovered vertex v that still has unexplored edges 5 4
• After all edges of v have been explored, the search
“backtracks” from the parent of v
• The process continues until all vertices reachable from the
original source have been discovered
• If undiscovered vertices remain, choose one of them as a
new source and repeat the search from that vertex
• DFS creates a “depth-first forest”
DFS Additional Data Structures
● Global variable: time-stamp
■ Incremented when nodes are discovered or finished
● color[u] – similar to BFS
■ White before discovery, gray while processing and black
when finished processing
● prev[u] – predecessor of u
● d[u], f[u] – discovery and finish times
1 ≤ d[u] < f [u] ≤ 2 |V|
WHITE GRAY BLACK
0 d[u] f[u] 2V
Depth-First Search: The Code
Data: color[V], time, DFS_Visit(u)
prev[V],d[V], f[V] {
DFS(G) // where prog starts color[u] = GREY;
{ time = time+1;
Initialize
d[u] = time;
for each vertex u V
for each v Adj[u]
{
{
color[u] = WHITE;
if(color[v] == WHITE){
prev[u]=NIL; prev[v]=u;
f[u]=inf; DFS_Visit(v);}
d[u]=inf; }
} color[u] = BLACK;
time = 0; time = time+1;
for each vertex u V f[u] = time;
if (color[u] == WHITE) }
DFS_Visit(u);
} 5
Depth-First Search: The Code
Data: color[V], time, DFS_Visit(u)
prev[V],d[V], f[V] {
DFS(G) // where prog starts color[u] = GREY;
{ time = time+1;
d[u] = time;
for each vertex u V
for each v Adj[u]
{
{
color[u] = WHITE;
if(color[v] == WHITE){
prev[u]=NIL; prev[v]=u;
f[u]=inf; DFS_Visit(v);}
d[u]=inf; }
} color[u] = BLACK;
time = 0; time = time+1;
for each vertex u V f[u] = time;
if (color[u] == WHITE) }
DFS_Visit(u);
} 6 What does d[u] represent?
Depth-First Search: The Code
Data: color[V], time, DFS_Visit(u)
prev[V],d[V], f[V] {
DFS(G) // where prog starts color[u] = GREY;
{ time = time+1;
d[u] = time;
for each vertex u V
for each v Adj[u]
{
{
color[u] = WHITE;
if(color[v] == WHITE){
prev[u]=NIL; prev[v]=u;
f[u]=inf; DFS_Visit(v);}
d[u]=inf; }
} color[u] = BLACK;
time = 0; time = time+1;
for each vertex u V f[u] = time;
if (color[u] == WHITE) }
DFS_Visit(u);
} 7 What does f[u] represent?
Depth-First Search: The Code
Data: color[V], time, DFS_Visit(u)
prev[V],d[V], f[V] {
DFS(G) // where prog starts color[u] = GREY;
{ time = time+1;
d[u] = time;
for each vertex u V
for each v Adj[u]
{
{
color[u] = WHITE;
if(color[v] == WHITE){
prev[u]=NIL; prev[v]=u;
f[u]=inf; DFS_Visit(v);
d[u]=inf; }}
} color[u] = BLACK;
time = 0; time = time+1;
for each vertex u V f[u] = time;
if (color[u] == WHITE) }
DFS_Visit(u);
Will all vertices eventually be colored black?
} 8
DFS Example
source
vertex
S D F
B C G
9
DFS Example
source
vertex
dS f D F
1 | | |
A
| |
E
| | |
B C G
10
DFS Example
source
vertex
dS f D F
1 | | |
A
2 | |
E
| | |
B C G
11
DFS Example
source
vertex
dS f D F
1 | | |
A
2 | |
E
3 | | |
B C G
12
DFS Example
source
vertex
dS f D F
1 | | |
A
2 | |
E
3 | 4 | |
B C G
13
DFS Example
source
vertex
dS f D F
1 | | |
A
2 | |
E
3 | 4 5 | |
B C G
14
DFS Example
source
vertex
dS f D F
1 | | |
A
2 | |
E
3 | 4 5 | 6 |
B C G
15
DFS Example
source
vertex
dS f D F
1 | | |
A
2 | 7 |
E
3 | 4 5 | 6 |
B C G
16
DFS Example
source
vertex
dS f D F
1 | 8 | |
A
2 | 7 |
E
3 | 4 5 | 6 |
B C G
17
DFS Example
source
vertex
dS f D F
1 | 8 | |
A
2 | 7 9 |
E
3 | 4 5 | 6 |
B C G
What is the structure of the grey vertices?
What do they represent?
18
DFS Example
source
vertex
dS f D F
1 | 8 | |
A
2 | 7 9 |10
E
3 | 4 5 | 6 |
B C G
19
DFS Example
source
vertex
dS f D F
1 | 8 |11 |
A
2 | 7 9 |10
E
3 | 4 5 | 6 |
B C G
20
DFS Example
source
vertex
dS f D F
1 |12 8 |11 |
A
2 | 7 9 |10
E
3 | 4 5 | 6 |
B C G
21
DFS Example
source
vertex
dS f D F
1 |12 8 |11 13|
A
2 | 7 9 |10
E
3 | 4 5 | 6 |
B C G
22
DFS Example
source
vertex
dS f D F
1 |12 8 |11 13|
A
2 | 7 9 |10
E
3 | 4 5 | 6 14|
B C G
23
DFS Example
source
vertex
dS f D F
1 |12 8 |11 13|
A
2 | 7 9 |10
E
3 | 4 5 | 6 14|15
B C G
24
DFS Example
source
vertex
dS f D F
1 |12 8 |11 13|16
A
2 | 7 9 |10
E
3 | 4 5 | 6 14|15
B C G
25
Depth-First Search: The Code
Data: color[V], time, DFS_Visit(u)
prev[V],d[V], f[V] {
DFS(G) // where prog starts color[u] = GREY;
{ time = time+1;
d[u] = time;
for each vertex u V
for each v Adj[u]
{
{
color[u] = WHITE;
if (color[v] == WHITE)
prev[u]=NIL; prev[v]=u;
f[u]=inf; DFS_Visit(v);
d[u]=inf; }
} color[u] = BLACK;
time = 0; time = time+1;
for each vertex u V f[u] = time;
if (color[u] == WHITE) }
DFS_Visit(u);
What will be the running time?
} 26
Depth-First Search: The Code
Data: color[V], time, DFS_Visit(u)
prev[V],d[V], f[V] {
DFS(G) // where prog starts color[u] = GREY;
{ time = time+1;
d[u] = time;
for each vertex u V
for each v Adj[u]
{ O(V)
{
color[u] = WHITE;
if (color[v] == WHITE)
prev[u]=NIL; O(V)
prev[v]=u;
f[u]=inf; DFS_Visit(v);
d[u]=inf; }
} color[u] = BLACK;
time = 0; O(V) time = time+1;
for each vertex u V f[u] = time;
if (color[u] == WHITE) }
DFS_Visit(u);
Running time: O(V2) because call DFS_Visit on each vertex,
} and the loop over Adj[] can
27 run as many as |V| times
Depth-First Search: The Code
Data: color[V], time, DFS_Visit(u)
prev[V],d[V], f[V] {
DFS(G) // where prog starts color[u] = GREY;
{ time = time+1;
d[u] = time;
for each vertex u V
for each v Adj[u]
{
{
color[u] = WHITE;
if (color[v] == WHITE)
prev[u]=NIL; prev[v]=u;
f[u]=inf; DFS_Visit(v);
d[u]=inf; }
} color[u] = BLACK;
time = 0; time = time+1;
for each vertex u V f[u] = time;
if (color[u] == WHITE) }
BUT, there is actually a tighter bound.
DFS_Visit(u);
} How many times will DFS_Visit()
28
actually be called?
Depth-First Search: The Code
Data: color[V], time, DFS_Visit(u)
prev[V],d[V], f[V] {
DFS(G) // where prog starts color[u] = GREY;
{ time = time+1;
d[u] = time;
for each vertex u V
for each v Adj[u]
{
{
color[u] = WHITE;
if (color[v] == WHITE)
prev[u]=NIL; prev[v]=u;
f[u]=inf; DFS_Visit(v);
d[u]=inf; }
} color[u] = BLACK;
time = 0; time = time+1;
for each vertex u V f[u] = time;
if (color[u] == WHITE) }
DFS_Visit(u);
} So, running time of DFS = O(V+E)
29
Depth-First Sort Analysis
● This running time argument is an informal
example of amortized analysis
■ “Charge” the exploration of edge to the edge:
○ Each loop in DFS_Visit can be attributed to an edge in the
graph
○ Runs once per edge if directed graph, twice if undirected
○ Thus loop will run in O(E) time, algorithm O(V+E)
Considered linear for graph, b/c adj list requires O(V+E) storage
■ Important to be comfortable with this kind of
reasoning and analysis
30
DFS: Kinds of edges
● DFS introduces an important distinction
among edges in the original graph:
■ Tree edge: encounter new (white) vertex
○ The tree edges form a spanning forest
○ Can tree edges form cycles? Why or why not?
No
31
DFS Example
source
vertex
d f
1 |12 8 |11 13|16
2 | 7 9 |10
3 | 4 5 | 6 14|15
Tree edges
32
DFS: Kinds of edges
● DFS introduces an important distinction
among edges in the original graph:
■ Tree edge: encounter new (white) vertex
■ Back edge: from descendent to ancestor
○ Encounter a grey vertex (grey to grey)
○ Self loops are considered as to be back edge.
33
DFS Example
source
vertex
d f
1 |12 8 |11 13|16
2 | 7 9 |10
3 | 4 5 | 6 14|15
Tree edges Back edges
34
DFS: Kinds of edges
● DFS introduces an important distinction
among edges in the original graph:
■ Tree edge: encounter new (white) vertex
■ Back edge: from descendent to ancestor
■ Forward edge: from ancestor to descendent
○ Not a tree edge, though
○ From grey node to black node
35
DFS Example
source
vertex
d f
1 |12 8 |11 13|16
2 | 7 9 |10
3 | 4 5 | 6 14|15
Tree edges Back edges Forward edges
36
DFS: Kinds of edges
● DFS introduces an important distinction
among edges in the original graph:
■ Tree edge: encounter new (white) vertex
■ Back edge: from descendent to ancestor
■ Forward edge: from ancestor to descendent
■ Cross edge: between a tree or subtrees
○ From a grey node to a black node
37
DFS Example
source
vertex
d f
1 |12 8 |11 13|16
2 | 7 9 |10
3 | 4 5 | 6 14|15
Tree edges Back edges Forward edges Cross edges
38
DFS: Kinds of edges
● DFS introduces an important distinction
among edges in the original graph:
■ Tree edge: encounter new (white) vertex
■ Back edge: from descendent to ancestor
■ Forward edge: from ancestor to descendent
■ Cross edge: between a tree or subtrees
● Note: tree & back edges are important; most
algorithms don’t distinguish forward & cross
39
More about the edges
● Let (u,v) is an edge.
■ If (color[v] = WHITE) then (u,v) is a tree edge
■ If (color[v] = GRAY) then (u,v) is a back edge
■ If (color[v] = BLACK) then (u,v) is a
forward/cross edge
○ Forward Edge: d[u]<d[v]
○ Cross Edge: d[u]>d[v]
40
Depth-First Search - Timestamps
a b s c
3/6 2/9 1/10 11/16
B F C B
4/5 7/8 12/13 14/15
d C e C f C g
41
Depth-First Search - Timestamps
s c
C B
F
b f g
C
a e C
B
C
d
42
Depth-First Search: Detect Edge
Data: color[V], time, DFS_Visit(u)
prev[V],d[V], f[V] {
color[u] = GREY;
DFS(G) // where prog starts
time = time+1;
{ d[u] = time;
for each vertex u V for each v Adj[u]
{ {
detect edge type using
color[u] = WHITE; “color[v]”
prev[u]=NIL; if(color[v] == WHITE){
f[u]=inf; prev[v]=u;
d[u]=inf; DFS_Visit(v);
}}
}
color[u] = BLACK;
time = 0; time = time+1;
for each vertex u V f[u] = time;
if (color[u] == WHITE) }
DFS_Visit(u);
} 43
DFS: Kinds Of Edges
● Thm 22.10: If G is undirected, a DFS produces
only tree and back edges
● Proof by contradiction:
source
■ Assume there’s a forward edge F?
○ But F? edge must actually be a
back edge (why?)
44
DFS: Kinds Of Edges
● Thm 23.9: If G is undirected, a DFS produces only
tree and back edges
● Proof by contradiction:
source
■ Assume there’s a cross edge
○ But C? edge cannot be cross:
○ must be explored from one of the
vertices it connects, becoming a tree
vertex, before other vertex is explored
○ So in fact the picture is wrong…both
lower tree edges cannot in fact be
tree edges
C?
45
DFS And Graph Cycles
● Thm: An undirected graph is acyclic iff a DFS
yields no back edges
■ If acyclic, no back edges (because a back edge implies a
cycle
■ If no back edges, acyclic
○ No back edges implies only tree edges (Why?)
○ Only tree edges implies we have a tree or a forest
○ Which by definition is acyclic
● Thus, can run DFS to find whether a graph has a
cycle
46
DFS And Cycles
How would you modify the code to detect cycles?
Data: color[V], time, DFS_Visit(u)
prev[V],d[V], f[V] {
DFS(G) // where prog starts color[u] = GREY;
{ time = time+1;
for each vertex u V d[u] = time;
{ for each v Adj[u]
color[u] = WHITE; {
prev[u]=NIL; if (color[v]==WHITE){
prev[v]=u;
f[u]=inf; d[u]=inf;
DFS_Visit(v);
}
}
time = 0;
}
for each vertex u V
color[u] = BLACK;
if (color[u] == WHITE) time = time+1;
DFS_Visit(u); f[u] = time;
} }
47
DFS And Cycles
What will be the running time?
Data: color[V], time, DFS_Visit(u)
prev[V],d[V], f[V] {
DFS(G) // where prog starts color[u] = GREY;
{ time = time+1;
for each vertex u V d[u] = time;
{ for each v Adj[u]
color[u] = WHITE; {
prev[u]=NIL; if (color[v]==WHITE){
prev[v]=u;
f[u]=inf; d[u]=inf;
DFS_Visit(v); }
}
else {cycle exists;}
time = 0;
}
for each vertex u V
color[u] = BLACK;
if (color[u] == WHITE) time = time+1;
DFS_Visit(u); f[u] = time;
} }
48
DFS And Cycles
● What will be the running time?
● A: O(V+E)
● We can actually determine if cycles exist in
O(V) time
■ How??
49
DFS And Cycles
● What will be the running time for undirected
graph to detect cycle?
● A: O(V+E)
● We can actually determine if cycles exist in
O(V) time:
■ In an undirected acyclic forest, |E| |V| - 1
■ So count the edges: if ever see |V| distinct edges,
must have seen a back edge along the way
50
DFS And Cycles
● What will be the running time for directed
graph to detect cycle?
● A: O(V+E)
51
Reference
● Cormen –
■ Chapter 22 (Elementary Graph Algorithms)
● Exercise –
■ 22.3-4 –Detect edge using d[u], d[v], f[u], f[v]
■ 22.3-11 – Connected Component
■ 22.3-12 – Singly connected
52