Applications of the depth-first search algorithm Undirected Graphs

Applications of the depth-first search algorithm
Undirected Graphs
Lecture 3
Mircea Marin
October 2013
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Outline
Applications of the depth-first search algorithm
Depth-first spanning forest
DAG recognition
Topological sort of DAGs
Computation of strong components of digraphs
Undirected graphs
Definition, main notions
Main operations
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Depth-first search
Given a graph G = (V , E) and a node s ∈ V
Find all nodes reachable by a path from s, by searching
"deeper" in the graph whenever possible.
Edges are explored out of the most recently
discovered vertex v that still has unexplored
edges leaving it.
When all of v ’s edges have been explored,
the algorithm "backtracks" to its parent node,
to explore other leaving edges.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Depth-first traversal (DFT)
Iterative version (see also Lecture 2)
procedure dfs(v : vertex)
first-visit-op(v )
/* first visit of v */
S:= a stack containing only node v
while S is not empty
u:=S.peek()
if u has unvisited neighbors
w:=the first unvisited neighbor of u
first-visit-op(w)
/* first visit of w */
mark[w]:=visited
S.push(w)
else
w:=S.pop()
last-visit-op(w)
/* last visit of w */
N OTES :
I mark is a global array (or map) initialized with
mark[w] := unvisited for all nodes w
I a node is marked as visited when it is first encountered.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Compare with breadth-first traversal
A simplified version of breadth first-search (see also Lecture 2)
procedure bfs(v : vertex)
first-visit-op(v )
/* first visit of v */
Q:= a queue containing only node v
while Q is not empty
extract last element u from Q
last-visit-op(u)
/* last visit of u */
for all neighbours w of u do
if mark[w] = unvisited
mark[w] := visited
first-visit-op(w)
/* first visit of w */
Q.push(w)
N OTES :
I mark is a global array (or map) initialized with
mark[w] := unvisited for all nodes w
I a node is marked as visited when it is first encountered.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Depth-first traversal (DFT)
Recursive version
DFT is more natural to describe recursively (pseudocode):
procedure dfs(v : vertex)
mark[v ] := visited
first-visit-op(v )
/* first visit of v */
for each neighbor w of v do
if mark[w]=unvisited then
dfs(w)
/* recursive call */
last-visit-op(v )
/* last visit of v */
N OTES :
I mark is a global array (or map) initialized with
mark[w] := unvisited for all nodes w
I a node is marked as visited when it is first visited.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of the depth-first search algorithm
Depth-first spanning forest
F
B
G
D
A
Consider the digraph G E
A 7→ [B, C]
with adjacency lists D 7→ [C]
F 7→ [B]
B 7→ [C, D]
E 7→ [F , G]
G 7→ [F , D]
C
C 7→ [A]
Some depth-first traversals of G do not visit all nodes of G:
A
B
C
D
I Nodes E, F , G are not visited.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of the depth-first search algorithm
Depth-first spanning forest
F
B
G
D
A
Consider the digraph G E
A 7→ [B, C]
with adjacency lists D 7→ [C]
F 7→ [B]
B 7→ [C, D]
E 7→ [F , G]
G 7→ [F , D]
C
C 7→ [A]
Some depth-first traversals of G do not visit all nodes of G:
A
B
C
D
I Nodes E, F , G are not visited.
By selecting unvisited nodes as long as possible and
restarting depth first traversal from them, we produce a
depth-first spanning forest.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of the depth-first search algorithm
Depth-first spanning forest
F
B
G
D
A
Consider the digraph G E
A 7→ [B, C]
with adjacency lists D 7→ [C]
F 7→ [B]
B 7→ [C, D]
E 7→ [F , G]
G 7→ [F , D]
C
C 7→ [A]
Some depth-first traversals of G do not visit all nodes of G:
E
A
F
B
C
G
D
I Nodes E, F , G are not visited.
By selecting unvisited nodes as long as possible and
restarting depth first traversal from them, we produce a
depth-first spanning forest.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of the depth-first search algorithm
Depth-first spanning forest
5
1
A
E
C
3
7
6
2
B
F
4
D
G
dfnumber [A] = 1
dfnumber [B] = 2
dfnumber [C] = 3
dfnumber [D] = 4
...
Drawing strategy:
The nodes of depth first-search tree are drawn from left to right, in the order of
their first visit.
Assign a number dfnumber [n] to every node n, starting from 1, in the order
in which they are visited first by the depth-first search.
The trees are drawn from left to right, in the order in which they are generated.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of the depth-first search algorithm
Depth-first spanning forest
5
1
A
E
C
3
7
6
2
B
F
4
D
G
dfnumber [A] = 1
dfnumber [B] = 2
dfnumber [C] = 3
dfnumber [D] = 4
...
Drawing strategy:
The nodes of depth first-search tree are drawn from left to right, in the order of
their first visit.
Assign a number dfnumber [n] to every node n, starting from 1, in the order
in which they are visited first by the depth-first search.
The trees are drawn from left to right, in the order in which they are generated.
Remarks: There are 4 kinds of arcs
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of the depth-first search algorithm
Depth-first spanning forest
5
1
A
E
C
3
7
6
2
B
F
4
D
G
dfnumber [A] = 1
dfnumber [B] = 2
dfnumber [C] = 3
dfnumber [D] = 4
...
Drawing strategy:
The nodes of depth first-search tree are drawn from left to right, in the order of
their first visit.
Assign a number dfnumber [n] to every node n, starting from 1, in the order
in which they are visited first by the depth-first search.
The trees are drawn from left to right, in the order in which they are generated.
Remarks: There are 4 kinds of arcs
1
The solid arcs connecting nodes in the depth-first search trees are tree arcs.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of the depth-first search algorithm
Depth-first spanning forest
5
1
A
E
C
3
7
6
2
B
F
4
D
G
dfnumber [A] = 1
dfnumber [B] = 2
dfnumber [C] = 3
dfnumber [D] = 4
...
Drawing strategy:
The nodes of depth first-search tree are drawn from left to right, in the order of
their first visit.
Assign a number dfnumber [n] to every node n, starting from 1, in the order
in which they are visited first by the depth-first search.
The trees are drawn from left to right, in the order in which they are generated.
Remarks: There are 4 kinds of arcs
1
The solid arcs connecting nodes in the depth-first search trees are tree arcs.
2
The other arcs, which are dashed, are of 3 kinds:
(1) back arcs: connect a node with an ancestor in its tree:
C → A, D → A
(2) forward arcs: connect a node with a descendant in its tree:
A→C
(3) cross arcs: all other arcs:
F → B, G → F , G → D
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of the depth-first search algorithm
Depth-first spanning forest
5
1
A
E
3
C
7
6
2
B
4
F
D
Mircea Marin
G
dfnumber [A] = 1
dfnumber [B] = 2
dfnumber [C] = 3
dfnumber [D] = 4
...
Applications of the depth-first search algorithm Undirected Graphs
Applications of the depth-first search algorithm
Depth-first spanning forest
5
1
A
E
3
C
7
6
2
B
4
F
D
G
dfnumber [A] = 1
dfnumber [B] = 2
dfnumber [C] = 3
dfnumber [D] = 4
...
Characterizations of the node relations by vertex numbering
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of the depth-first search algorithm
Depth-first spanning forest
5
1
A
E
3
C
7
6
2
B
4
F
D
G
dfnumber [A] = 1
dfnumber [B] = 2
dfnumber [C] = 3
dfnumber [D] = 4
...
Characterizations of the node relations by vertex numbering
1
A node u is a descendant of v iff dfnumber [v ] ≤ dfnumber [u] ≤ dfnumber [v ]+
number of descendants of v . Thus:
forward arcs go from low-numbered nodes to high-numbered nodes.
back arcs go from high-numbered nodes to low-numbered nodes.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of the depth-first search algorithm
Depth-first spanning forest
5
1
A
E
3
C
7
6
2
B
4
F
D
G
dfnumber [A] = 1
dfnumber [B] = 2
dfnumber [C] = 3
dfnumber [D] = 4
...
Characterizations of the node relations by vertex numbering
1
A node u is a descendant of v iff dfnumber [v ] ≤ dfnumber [u] ≤ dfnumber [v ]+
number of descendants of v . Thus:
forward arcs go from low-numbered nodes to high-numbered nodes.
back arcs go from high-numbered nodes to low-numbered nodes.
2
All cross arcs go from high-numbered to low-numbered nodes.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Directed acyclic graphs (DAGs)
A directed acyclic graph (DAG for short) is a digraph without cycles.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Directed acyclic graphs (DAGs)
A directed acyclic graph (DAG for short) is a digraph without cycles.
1 DAGs are useful in representing the syntactic structure of arithmetic expressions
with common subexpressions.
Example (DAG for (a + b) ∗ c + ((a + b) + e) ∗ (e + f )) ∗ (a + b) ∗ c)
+
∗
+
∗
a
∗
+
+
c
e
f
b
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Directed acyclic graphs (DAGs)
A directed acyclic graph (DAG for short) is a digraph without cycles.
1 DAGs are useful in representing the syntactic structure of arithmetic expressions
with common subexpressions.
Example (DAG for (a + b) ∗ c + ((a + b) + e) ∗ (e + f )) ∗ (a + b) ∗ c)
+
∗
+
∗
a
2
∗
+
+
c
e
f
b
DAGs can be used to represent partial orders (=irreflexive and transitive).
Example (DAG for the relation ⊂ between subsets of {1, 2, 3})
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of depth-first search
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of depth-first search
1
Test for acyclicity: Determine whether a digraph is acyclic.
Solution: Generate a depth-first spanning forest.
The digraph is acyclic iff it contains a back arc.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of depth-first search
1
Test for acyclicity: Determine whether a digraph is acyclic.
Solution: Generate a depth-first spanning forest.
The digraph is acyclic iff it contains a back arc.
2
Topological sort
Scenario
A large project is often divided into a collection of smaller tasks, some of which have to
be performed in certain specified orders so that we may complete the entire project.
For example, a university curriculum may have courses that require other courses as
prerequisites. We can model the required orders with a DAG, e.g.:
C1
C3
C5
C2
C4
Requirement: Assign a linear ordering to the nodes of a DAG s.t. if there is an arc
from i to j then i occurs before j in the linear ordering.
The linear ordering is called a topological sort.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of depth-first search
1
Test for acyclicity: Determine whether a digraph is acyclic.
Solution: Generate a depth-first spanning forest.
The digraph is acyclic iff it contains a back arc.
2
Topological sort
Scenario
A large project is often divided into a collection of smaller tasks, some of which have to
be performed in certain specified orders so that we may complete the entire project.
For example, a university curriculum may have courses that require other courses as
prerequisites. We can model the required orders with a DAG, e.g.:
C1
C3
C5
C2
C4
Requirement: Assign a linear ordering to the nodes of a DAG s.t. if there is an arc
from i to j then i occurs before j in the linear ordering.
The linear ordering is called a topological sort.
Topological sort can be accomplished easily with depth first search.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of Depth-First Search
Topological sort using depth-first search
topsort(node v) is the depth-first search procedure adjusted with a statement
to print the nodes accessible from a node v in reverse topological order.
Pseudocode
void topsort(node v) {
nodeColor[v]=BLACK;
for every node w adjacent to v do
if (nodeColor[w] == WHITE) {
topsort(w);
}
cout << v.getName();
}
Mircea Marin
// mark v as visited
// if w is not visited
Applications of the depth-first search algorithm Undirected Graphs
Applications of Depth-First Search
Topological sort using depth-first search
topsort(node v) is the depth-first search procedure adjusted with a statement
to print the nodes accessible from a node v in reverse topological order.
Pseudocode
void topsort(node v) {
nodeColor[v]=BLACK;
for every node w adjacent to v do
if (nodeColor[w] == WHITE) {
topsort(w);
}
cout << v.getName();
}
Mircea Marin
// mark v as visited
// if w is not visited
Applications of the depth-first search algorithm Undirected Graphs
Applications of Depth-First Search
Topological sort using depth-first search
topsort(node v) is the depth-first search procedure adjusted with a statement
to print the nodes accessible from a node v in reverse topological order.
Pseudocode
void topsort(node v) {
nodeColor[v]=BLACK;
for every node w adjacent to v do
if (nodeColor[w] == WHITE) {
topsort(w);
}
cout << v.getName();
}
// mark v as visited
// if w is not visited
I Remark. When topsort finishes searching all nodes adjacent to a node x, it
prints x.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of Depth-First Search
Topological sort using depth-first search
topsort(node v) is the depth-first search procedure adjusted with a statement
to print the nodes accessible from a node v in reverse topological order.
Pseudocode
void topsort(node v) {
nodeColor[v]=BLACK;
for every node w adjacent to v do
if (nodeColor[w] == WHITE) {
topsort(w);
}
cout << v.getName();
}
// mark v as visited
// if w is not visited
I Remark. When topsort finishes searching all nodes adjacent to a node x, it
prints x.
⇒ topsort(v ) will print in a reverse topological order all nodes of a DAG which
are accessible from v by a path in the DAG.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of Depth-First Search
Strong components
Assumption: G = (V , E) is a digraph.
A strongly connected component of G is a subgraph (V 0 , E 0 ) of
G where V 0 is a maximal subset of V s.t. there is a path from
any node in the set to any other node in the set.
v ≡ w iff there exists a path from v to w and also a path
from w to v is an equivalence relation on V
⇒ V can be partitioned into a family {Vi | 1 ≤ i ≤ r } of
equivalence classes w.r.t. ≡, and then build the strong
components Gi = (Vi , Ei ) of G.
A digraph with only one strong component is called
strongly connected.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of Depth-First Search
Strong components
Assumption: G = (V , E) is a digraph.
A strongly connected component of G is a subgraph (V 0 , E 0 ) of
G where V 0 is a maximal subset of V s.t. there is a path from
any node in the set to any other node in the set.
v ≡ w iff there exists a path from v to w and also a path
from w to v is an equivalence relation on V
⇒ V can be partitioned into a family {Vi | 1 ≤ i ≤ r } of
equivalence classes w.r.t. ≡, and then build the strong
components Gi = (Vi , Ei ) of G.
A digraph with only one strong component is called
strongly connected.
Example
a
b
a
b
d
c
has 2 strong components:
d
c
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of Depth-First Search
Strong components
Remarks
Every node of a digraph belongs to a strong component.
Some arcs of a digraph may not belong to a strong component. Such arcs are
cross-component arcs.
The strong components of a digraph G can be found by constructing a reduced
graph G0 of G:
I the nodes of G0 are the strong components of G
I there is an arc from C in C 0 in G0 iff there is an arc in G
from some node in C to some node in C 0 .
Example:
a, b, c
a
b
d
c
has the reduced graph
d
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Applications of Depth-First Search
Computation of strong components
1
Perform a depth-first search of G and number the nodes in
post-order traversal of the depth-first search tree (that is,
assign to the parent node a larger number than to its
children)
2
Construct the digraph Gr obtained from G by reversing the
direction of all its arcs.
3
Perform depth-first search of Gr , starting the search from
the node with highest number assigned in step 1. If
depth-first search does not reach all nodes, start the next
depth-first search from the highest-numbered remaining
node.
4
Each tree in the resulting spanning forest is a strongly
connected component of G.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Computation of strong components
Example
a
b
4
a
b
d
c
1
d
c
Fig. 1
Fig. 2
Mircea Marin
3
2
4
a
2
c
3
b
d
1
Fig. 3
Applications of the depth-first search algorithm Undirected Graphs
Computation of strong components
Example
a
b
4
a
b
d
c
1
d
c
Fig. 1
Fig. 2
3
2
4
a
2
c
3
b
d
1
Fig. 3
I Start performing depth-first search from node a in Fig. 1;
number increasingly the vertices during the time of their
last visit (step 1) and revert the arcs of G (step 2) ⇒
digraph Gr shown in Fig. 2.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Computation of strong components
Example
a
b
4
a
b
d
c
1
d
c
Fig. 1
Fig. 2
3
2
4
a
2
c
3
b
d
1
Fig. 3
I Start performing depth-first search from node a in Fig. 1;
number increasingly the vertices during the time of their
last visit (step 1) and revert the arcs of G (step 2) ⇒
digraph Gr shown in Fig. 2.
I Perform depth-first search in Gr starting with a because a
has highest assigned number. The first depth-first search
tree will contain nodes a, b, c. Then, continue with root d to
build the next depth-first search tree . . .
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Computation of strong components
Example
a
b
4
a
b
d
c
1
d
c
Fig. 1
Fig. 2
3
2
4
a
2
c
3
b
d
1
Fig. 3
I Start performing depth-first search from node a in Fig. 1;
number increasingly the vertices during the time of their
last visit (step 1) and revert the arcs of G (step 2) ⇒
digraph Gr shown in Fig. 2.
I Perform depth-first search in Gr starting with a because a
has highest assigned number. The first depth-first search
tree will contain nodes a, b, c. Then, continue with root d to
build the next depth-first search tree . . .
⇒ Depth-first spanning forest shown in Fig. 3.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Computation of strong components
Example
a
b
4
a
b
d
c
1
d
c
Fig. 1
Fig. 2
3
2
4
a
2
c
3
b
d
1
Fig. 3
I Start performing depth-first search from node a in Fig. 1;
number increasingly the vertices during the time of their
last visit (step 1) and revert the arcs of G (step 2) ⇒
digraph Gr shown in Fig. 2.
I Perform depth-first search in Gr starting with a because a
has highest assigned number. The first depth-first search
tree will contain nodes a, b, c. Then, continue with root d to
build the next depth-first search tree . . .
⇒ Depth-first spanning forest shown in Fig. 3.
Each tree of the forest forms a strong component of the
original graph.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Undirected graphs
G = (V , E) where
V = finite set of vertices (or nodes)
E = finite set of edges between nodes.
Every edge e ∈ E connects two nodes u, v ∈ V called the nodes incident to e.
An undirected graph can be
simple: there is at most one edge between any two nodes. An edge between
u
v
nodes u, v is represented as u−v and drawn as
.
It is assumed that edges are unordered, thus u−v = v −u.
If u−v is an edge than we say nodes u and v are adjacent.
multiple: there can be more than one edge between two nodes.
Distinct edges between same nodes are distinguished by labeling
them. An edge with label e between nodes u and v is represented as
e
e
u
v
u − v and drawn as
.
e
e
It is assumed that edges are unordered, thus u − v = v − u.
path = sequence of nodes π = v1 , . . . , vn such that v1 −v2 , . . . , vn−1 −vn ∈ E.
The length of π is n − 1. π is a path between v1 and vn .
simple path = path with distinct nodes, except possibly the first and last.
simple cycle = path of length at least 1 that begins ad ends at the same node.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Examples of undirected graphs
Acquaintanceship graph=simple graph where edges connect
people that know each other.
Computer network: multigraph where edges are between cities
linked by computer connections.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Auxiliary notions
Assumption: G = (V , E) undirected graph.
Subgraph of G: G0 = (V 0 , E 0 ) where V 0 ⊆ V and E 0 = the set of edges in E
between nodes in V 0 .
a
b
d
c
V = {a, b, c, d}
a
b
c
V0
= {a, b, c}
Two nodes are connected if there is a path between them.
A connected component of G is a subgraph G0 = (V 0 , E 0 ) with V 0 maximal such
that every u, v ∈ V 0 are connected.
Figure : An unconnected graph with 2 connected components
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Undirected graphs: Methods of Representation
Adjacency matrix, adjacency lists, and edge list
a
b
d
c
1
Adjacency matrix
Note: This is a symmetric matrix.
2
Adjacency lists
3
Edge list: [a−b, b−c, c−d, d−a, d−b]
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
Operations on Undirected Graphs
I All operations on directed graphs carry over to undirected
graphs, with the difference that every undirected edge u−v may
be thought as the pair of directed edges u → v and v → u.
I Terminology specific to unconnected graphs G = (V , E)
Connected component = maximal connected induced
subgraph G0 = (V 0 , E 0 ) of G, that is:
B All nodes of V 0 are connected
B There is no path between a node in V 0 and a node in V − V 0 .
Free tree = a connected acyclic graph.
Properties of depth-first spanning forests in undirected graphs:
1
2
There is no distinction between forward and backward
edges.
There are no cross edges, that is, edges v −w such that v
is neither ancestor nor descendant of w.
⇒ all edges are either tree edges or back edges.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs
References
I Alfred V. Aho et al. Data Structures and Algorithms.
Chapters 6 and 7.
I K. H. Rosen. Discrete Mathematics and Its Applications.
Chapter 9.
Mircea Marin
Applications of the depth-first search algorithm Undirected Graphs