Editing Depth-first search
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.
The edit can be undone.
Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 55: | Line 55: | ||
==The DFS tree== | ==The DFS tree== | ||
− | |||
===Undirected graphs=== | ===Undirected graphs=== | ||
− | When we run DFS on | + | Assume we have an undirected graph consisting of a single connected component. When we run DFS on this graph, we generally consider it as a directed graph in which every edge is bidirectional. (This is akin to adding an arrowhead to each end of each edge in a diagram of the graph using circles and line segments.) Running DFS on this graph selects some of the edges (<math>|V|-1</math> of them, to be specific) to form a spanning tree. Note that these edges point generally away from the source. They are known as '''tree edges'''. When we traverse a tree link, we make a recursive call to a previously unvisited vertex. The directed edges running in the reverse direction - from a node to its parent in the DFS tree - are known as '''parent edges''', for obvious reasons. They correspond to a recursive call reaching the end of the function and returning to the caller. The remaining edges are all classified as either '''down edges''' or '''back edges'''. If a edge points from a node to one of its descendants in the spanning tree rooted at the source vertex, but it is not a tree edge, then it is a down edge; otherwise, it points to an ancestor, and if it is not a parent edge then it is a back edge. In the recursive implementation given, encountering either a down edge or a back edge results in an immediate return as the vertex has already been visited. Evidently, the reverse of a down edge is always a back edge and ''vice versa''. |
Every (directed) edge in the graph must be classifiable into one of the four categories: tree, parent, down, or back. To see this, suppose that the edge from node A to node B in some graph does fit into any of these categories. Then, in the spanning tree, A is neither an ancestor nor a descendant of B. This means that the lowest common ancestor of A and B in the spanning tree (which we will denote as C) is neither A nor B. Evidently, C is visited before either A or B, and A and B lie in different subtrees rooted at immediate children of C. So at some point C has been visited but none of its descendants have been visited. Now, because DFS always visits an entire subtree of the current vertex before backtracking and entering another subtree, the entire subtree containing either A or B (whichever one is visited first) must be explored before visiting the subtree containing the other. Suppose the subtree containing A is visited first. Then, when A is visited, B has not yet been visited, and thus the edge between them must be a tree edge, which is a contradiction. | Every (directed) edge in the graph must be classifiable into one of the four categories: tree, parent, down, or back. To see this, suppose that the edge from node A to node B in some graph does fit into any of these categories. Then, in the spanning tree, A is neither an ancestor nor a descendant of B. This means that the lowest common ancestor of A and B in the spanning tree (which we will denote as C) is neither A nor B. Evidently, C is visited before either A or B, and A and B lie in different subtrees rooted at immediate children of C. So at some point C has been visited but none of its descendants have been visited. Now, because DFS always visits an entire subtree of the current vertex before backtracking and entering another subtree, the entire subtree containing either A or B (whichever one is visited first) must be explored before visiting the subtree containing the other. Suppose the subtree containing A is visited first. Then, when A is visited, B has not yet been visited, and thus the edge between them must be a tree edge, which is a contradiction. | ||
Line 101: | Line 100: | ||
==Applications== | ==Applications== | ||
− | DFS, by virtue of being a subcategory of graph search, is able to find [[Graph theory#Types of graphs|connected component]]s, paths (including [[Maximum flow|augmenting paths]]), [[Tree|spanning trees]], and [[Topological sorting|topological orderings]] in linear time. The special properties of DFS | + | DFS, by virtue of being a subcategory of graph search, is able to find [[Graph theory#Types of graphs|connected component]]s, paths (including [[Maximum flow|augmenting paths]]), [[Tree|spanning trees]], and [[Topological sorting|topological orderings]] in linear time. The special properties of DFS also make it uniquely suitable for finding [[biconnected component]]s (or [[bridge]]s and [[articulation point]]s) and [[strongly connected component]]s. There are three well-known algorithms for the latter, those of [[Tarjan's strongly connected components algorithm|Tarjan]], [[Kosaraju's algorithm|Kosaraju]], and [[Gabow's algorithm|Gabow]]. The [[Finding cut vertices and edges|classic algorithm]] for the former appears to have no unique name in the literature. |
− | The following example shows how to find connected components and a | + | The following example shows how to find connected components and a spanning forest (a collection of spanning trees, one for each connected component) with DFS. |
<pre> | <pre> | ||
function DFS(u,v) | function DFS(u,v) |