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
© Copyright 2025 Paperzz