< Day Day Up > |
By relaxing the edges of a weighted dag (directed acyclic graph) G = (V, E) according to a topological sort of its vertices, we can compute shortest paths from a single source in Θ(V + E) time. Shortest paths are always well defined in a dag, since even if there are negative-weight edges, no negative-weight cycles can exist.
The algorithm starts by topologically sorting the dag (see Section 22.4) to impose a linear ordering on the vertices. If there is a path from vertex u to vertex v, then u precedes v in the topological sort. We make just one pass over the vertices in the topologically sorted order. As we process each vertex, we relax each edge that leaves the vertex.
DAG-SHORTEST-PATHS(G, w, s)
1 topologically sort the vertices of G
2 INITIALIZE-SINGLE-SOURCE(G, s)
3 for each vertex u, taken in topologically sorted order
4 do for each vertex v ∈ Adj[u]
5 do RELAX(u, v, w)
Figure 24.5 shows the execution of this algorithm.
The running time of this algorithm is easy to analyze. As shown in Section 22.4, the topological sort of line 1 can be performed in Θ(V + E) time. The call of INITIALIZE-SINGLE-SOURCE in line 2 takes Θ(V) time. There is one iteration per vertex in the for loop of lines 3-5. For each vertex, the edges that leave the vertex are each examined exactly once. Thus, there are a total of |E| iterations of the inner for loop of lines 4-5. (We have used an aggregate analysis here.) Because each iteration of the inner for loop takes Θ(1) time, the total running time is Θ(V + E), which is linear in the size of an adjacency-list representation of the graph.
The following theorem shows that the DAG-SHORTEST-PATHS procedure correctly computes the shortest paths.
![]() |
If a weighted, directed graph G = (V, E) has source vertex s and no cycles, then at the termination of the DAG-SHORTEST-PATHS procedure, d[v] = δ(s, v) for all vertices v ∈ V, and the predecessor subgraph Gπ is a shortest-paths tree.
Proof We first show that d[v] = δ(s, v) for all vertices v ∈ V at termination. If v is not reachable from s, then d[v] = δ(s, v) = ∞ by the no-path property. Now, suppose that v is reachable from s, so that there is a shortest path p = 〈v0, v1,..., vk〉, where v0 = s and vk = v. Because we process the vertices in topologically sorted order, the edges on p are relaxed in the order (v0, v1), (v1, v2),..., (vk-1, vk). The path-relaxation property implies that d[vi] = δ(s, vi) at termination for i = 0, 1,..., k. Finally, by the predecessor-subgraph property, Gπ is a shortest-paths tree.
![]() |
An interesting application of this algorithm arises in determining critical paths in PERT chart[2] analysis. Edges represent jobs to be performed, and edge weights represent the times required to perform particular jobs. If edge (u, v) enters vertex v and edge (v, x) leaves v, then job (u, v) must be performed prior to job (v, x). A path through this dag represents a sequence of jobs that must be performed in a particular order. A critical path is a longest path through the dag, corresponding to the longest time to perform an ordered sequence of jobs. The weight of a critical path is a lower bound on the total time to perform all the jobs. We can find a critical path by either
negating the edge weights and running DAG-SHORTEST-PATHS, or
running DAG-SHORTEST-PATHS, with the modification that we replace "∞" by "-∞" in line 2 of INITIALIZE-SINGLE-SOURCE and ">" by "<" in the RELAX procedure.
![]() |
Suppose we change line 3 of DAG-SHORTEST-PATHS to read
3 for the first |V| - 1 vertices, taken in topologically sorted order
Show that the procedure would remain correct.
![]() |
![]() |
The PERT chart formulation given above is somewhat unnatural. It would be more natural for vertices to represent jobs and edges to represent sequencing constraints; that is, edge (u, v) would indicate that job u must be performed before job v. Weights would then be assigned to vertices, not edges. Modify the DAG-SHORTEST-PATHS procedure so that it finds a longest path in a directed acyclic graph with weighted vertices in linear time.
![]() |
![]() |
Give an efficient algorithm to count the total number of paths in a directed acyclic graph. Analyze your algorithm.
![]() |
[2]"PERT" is an acronym for "program evaluation and review technique."
< Day Day Up > |