[-------------------------v1-----------------------]
[-------v2------] [-------------v6-------------]
[----v3---] [----------v5----------]
[-v4-] [------v7------]
[---v8---]
[-v9-]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Tree edges: (v1,v2), (v2,v3), (v1,v6), (v6,v5), (v5,v7), (v7,v8), (v8,v9)
Back edges: (v5,v6), (v9,v8)
Cross edges: (v8,v4), (v9,v3), (v5,v4)
There are no forward edges.
Two possible vertices are \(v_2\) and \(v_9\). The tree for \(v_2\) would only have the root of \(v_2\), \(v_3\) as its child, and v4 as its grandchild. The tree for \(v_9\) would have \(v_9\) as the root with 2 children being \(v_3\) and \(v_8\), and then one more grandchild, \(v_4\), attached to \(v_3\). We see that both the trees have the \(v_3\) and \(v_4\) vertices, but they each have other vertices in their tree.
Add a clock and two vertex attributes:
DFS(v, clock):
mark v
clock <- clock + 1; v.pre <- clock
for each edge vw
if w is unmarked
w.parent <- v
clock <- DFS(w, clock)
clock <- clock + 1; v.post <- clock
return clockv.pre is the clock value when the vertex v is first discovered and marked.
v.post is the clock value when we are done exploring v.
Suppose we run DFS on a graph \(G\).
v.pre.v.post.If \(G\) is a tree, these notions are the same as preorder/postorder traversals.
For any two vertices u and v, exactly one of the following must hold:
[u.pre..u.post] and [v.pre..v.post] do not overlap.
[u.pre..u.post] is contained in [v.pre..v.post].
u is a descendant of v in a depth-first tree.[v.pre..v.post] is contained in [u.pre..u.post].
v is a descendant of u in a depth-first tree.Notice: .pre and .post must be nested like parentheses:
Every edge uv in the graph is one of the following.
uv is in a/the depth-first tree.
DFS(u) calls DFS(v) directly, so u = v.parent.v is a descendant of u, but not its child.
u.pre \(<\) v.pre \(<\) v.post \(<\) u.post
uv goes backwards up a depth-first tree.
v.pre \(<\) u.pre \(<\) u.post \(<\) v.post
uv connects different branches in the depth-first forest.
v.post \(<\) u.pre
u \(\rightarrow\) v from u to v.
[u.pre..u.post] is contained in [v.pre..v.post], then u is a descendant of v in a depth-first tree.
u.post \(<\) v.post.uv is a back edge.v to u.uv is part of a cycle.So we can determine if a graph contains a cycle:
DoesGraphHaveACycle(G)
for each edge uv in G:
if u.post < v.post return "Graph has a cycle"
return "Graph has no cycles"
DFS(v, clock):
mark v
clock <- clock + 1; v.pre <- clock
for each edge vw
if w is unmarked
w.parent <- v
clock <- DFS(w, clock)
clock <- clock + 1; v.post <- clock
return clock// wrapper: // Modified DFS:
IsAcyclic(G): IsAcyclicDFS(v):
for all vertices v v.status <- Active
v.status <- New for each edge vw
for all vertices v if w.status = Active
if v.status = New return False
if IsAcyclicDFS(v) = False else if w.status = New
return False if IsAcyclicDFS(w) = False
return True return False
v.status <- Finished
return TrueA directed graph without cycles is called a directed acyclic graph (DAG).
Suppose \(G\) is a DAG.
.post. (Reverse postordering)See Figure 6.8.
TopologicalSort(G):
Call DFSAll(G) to compute finishing times v.post for all v in G
Return vertices in order of decreasing finishing times
DFS(v, clock):
mark v
clock <- clock + 1; v.pre <- clock
for each edge vw
if w is unmarked
w.parent <- v
clock <- DFS(w, clock)
clock <- clock + 1; v.post <- clock
return clock
DFSAll(G):
clock <- 0
for all vertices v
unmark v
for all vertices v
if v is unmarked
clock <- DFS(v, clock)
TopologicalSort(G):
Call DFSAll(G) to compute finishing times v.post for all v in G
Return vertices in order of decreasing finishing times
Facts:
| Table #1 | Table #2 | Table #3 | Table #4 | Table #5 | Table #6 | Table #7 |
|---|---|---|---|---|---|---|
| Andrew | John | Logan | Jordan | Bri | Levi | Jack |
| Drake | Josiah | Ethan | Kristen | Blake | Talia | Trevor |
| Grace | Isaac | Claire | Nathan | Kevin | Graham | James |
DFS, assume that the for-loops consider the vertices in numerical order. Include the starting and finishing times for each vertex.How many sources and sinks are there in this DAG?
Now suppose DFSAll considers vertex 6 first, and then vertex 1. Repeat question 1, and note any differences.
What relation does this DAG model? Are there other topological orderings for this DAG?