# CMPSCI 311: Theory of Algorithms

### Fun With Depth-First Search

Questions in black, answers in blue

Here are two graphs in adjacency list format. G is undirected and H is directed:

• G}: (1: 3, 4, 5), (2: 3, 6), (3: 1, 2, 5, 6), (4: 1), (5: 1, 3), (6: 2, 3)

• H: (A: B), (B: A, E), (C: B), (D: A), (E: C, D).

• Question 1: Draw G and H and draw a DFS forest for each. Identify tree, back, forward, and cross edges (if any) in each DFS forest.

Since I'm not good at HTML pictures, I'll skip the drawing of the graphs and just describe the DFS forests verbally.

The root of G's forest is vertex 1. From 1 we search 3, then 2, then 6, so we get a chain of tree edges from 1 to 3 to 2 to 6. During this search we discover a back edges from 6 to 3. Finishing 6 and 2, we return to 3 and find 5, which has a back edge to 1. Finishing 3, we return to 1 and search 4, so there is a tree edge from 1 to 4. Thus in the tree, 1 has children 3 and 4, 3 has children 2 and 5, 2 has child six, and we found two back edges for seven total edges.

The root of H's forest is A. A has child B, B has a back edge to A and a tree edge to E, E has tree edges to C and D, with C having a back edge to B and D having a back edge to A. There are seven total edges, four tree edges and three back edges.

• Question 2: It should be true that every non-tree edge in G's forest goes from some vertex v to an ancestor of v in the forest. Explain why this is always the case for an undirected graph. (Clarification: Following Levitin, when doing a DFS of an undirected graph we add an edge to the forest only the first time we see it, not the second time we see it in the other direction.)

Consider the situation when we are searching v and first encounter the edge from v to w. If w has not yet been visited, (v,w) becomes a tree edge. If w has been visited but is still being processed, it must be an ancestor of v because the dfs(w) process can only still be running if some descendent of w is being searched. So in this case (v,w) becomes a back edge, unless w is the parent of v in which case it doesn't go in the forest at all. If the dfs(w) process has been completed, all edges out of w have been checked, including the edge (w,v) that must exist since (v,w) exists and the graph is undirected. So (v,w) is the second occurrence of the edge between v and w, and thus does not go into the DFS forest at all.

• Question 3: A directed graph is strongly connected if there is a path from every vertex to every other vertex. Is H strongly connected? Explain how you would determine from a graph's DFS forest whether it is strongly connected.

H is strongly connected. There is a path from A down the tree to any other vertex. And we can reach A from both leaves of the tree, from D directly by the back edge to A and from C via the back edge to B and then the back edge to A.

In general a directed graph is strongly connected iff (a) its DFS forest is a tree, and (b) there is a path from each leaf of this tree to the root.

(Proof of this:) Clearly if the forest is not a tree, or it there is a leaf with no path to the root, we are not strongly connected. If (a) and (b) both hold, and x and y are any two vertices, there is a path from x down to some leaf, by the path given by (b) to the root, then down the tree to y.

Another way to say this is that the graph is not strongly connected iff there is a node x, other than the root, with the property that every back edge from a descendent of x goes to x or a descendent of x. We can determine whether this is true while doing a DFS, by having the process dfs(v) also report back the highest node reached by a back edge from v or one of its descendents.

• Question 4: A vertex v in a connected undirected graph is called an articulation point if removing v makes its graph unconnected. Are there any articulation points in G? Explain how to identify articulation points from a graph's DFS forest.

Because the graph is connected, we know that the DFS forest is a tree. The root is an articulation point iff it has exactly one child in this tree. (Proof: If all other codes are connected to the single child, removing the root does not disconnect the graph. If there is a node not reachable from the first child without going through the root, the first such node will become the second child.)

A non-root node is an articulation point if all back edges from it or its descendents go to it or its descendents. (Proof: If there is a way out of this node's subtree without using this node, it must be by a back edge to one of its ancestors. If there is such a back edge, removing the node does not disconnect the graph.

We test this property much as in Question 3, with each dfs(v) process reporting back the highest node reachable by a back edge from v or one of its descendents.