A necessary and sufficient condition for shortest path from a source vertex s to all reachable vertices w in a digraph applies to the array distTo no matter how it is calculated, provided it has these properties:
distTo[v] = length of some path from s to v, or
distTo[v] = Infinity if there is no directed path from s to v
A necessary and sufficient condition for distTo[u] to be the shortest distance from s to u for every vertex u is
For every vertex v and every edge e
distTo[w] <= distTo[v] + e.weight() (where v = e.from() and w = e.to())
The optimality condition is necessary for distTo[u] to be the minimal length of paths from s to u.
If
distTo[w] > distTo[v] + e.weight() for some v, w, and edge
v-> w
The path from s to v followed by the edge from v to w would have total length
distTo[v] + e.weight()
And so dist[w] would not be a minimal length for a path from s to w.
Suppose e is an edge from v to a vertex w.
distTo[v] is the length of some path from s to v
distTo[w] is the length of some path from s to w
We may be able to relax (i.e., decrease distTo[w]) by considering a different path from s to w:
s to v, followed by the edge from v to w.
whose length is
distTo[v] + e.weight() // where e is the edge from v to w
void relax(DirectedEdge e)
{
int v = e.from();
int w = e.to();
if (distTo[w] > distTo[v] + e.weight()) {
distTo[w] = distTo[v] + e.weight();
edgeTo[w] = v;
}
}
Shortest Path from a single source vertex in a weighted digraph with no negative weights
For the graph algorithm to solve this problem, we needed to pick a vertex of minimum distance to the source from the vertices that are connected by an edge to "known" vertices.
The distTo[v] array will keep track of the best distance so far from the source to vertex v.
But this distance might decrease by using a path through a vertex chosen later!
What data structure? We want to know what vertex to add next to the ones with known shortest distance.
A minPriorityQueue seems a possibly good choice with (vertex, distance) pairs, where the distance is the priority.
But there is a problem. How do we update the distance for some vertex that is already in the priority queue.
Example in class
| IndexMinPQ<Key> |
|---|
| (private members) |
|
insert(int v, Key k): void delMin(): int change(int v, Key k): void contains(int v): boolean ... |
Shortest directed paths from a source vertex s.

public DijkstraSP(EdgeWeightedDigraph G, int s) {
distTo = new double[G.V()];
edgeTo = new DirectedEdge[G.V()];
for (int v = 0; v < G.V(); v++) {
distTo[v] = Double.POSITIVE_INFINITY;
}
distTo[s] = 0.0;
// relax vertices in order of distance from s
pq = new IndexMinPQ<Double>(G.V());
pq.insert(s, distTo[s]);
while (!pq.isEmpty()) {
int v = pq.delMin();
for (DirectedEdge e : G.adj(v))
relax(e);
}
}
}
|
private void relax(DirectedEdge e) {
int v = e.from(), w = e.to();
if (distTo[w] > distTo[v] + e.weight()) {
distTo[w] = distTo[v] + e.weight();
edgeTo[w] = e;
if (pq.contains(w)) {
pq.change(w, distTo[w]);
} else {
pq.insert(w, distTo[w]);
}
}
}
|
Find the shortest path in an edge weighted DAG (no cycles), but allow negative weights.
public AcyclicSP(EdgeWeightedDigraph G, int s) {
distTo = new double[G.V()];
edgeTo = new DirectedEdge[G.V()];
for (int v = 0; v < G.V(); v++)
distTo[v] = Double.POSITIVE_INFINITY;
distTo[s] = 0.0;
// visit vertices in toplogical order
Topological topological = new Topological(G);
for (int v : topological.order()) {
for (DirectedEdge e : G.adj(v))
relax(e);
}
}
How do you find longest paths from a source vertex in an edge weighted graph?
DijkstraSP doesn't help.
AcyclicSP does with a simple observation.
Switch to a copy of the graph, but with all the edge weights negated.
Find the shortest path in the copy.
The same sequence of vertices will be a longest path in the original graph!
AcyclicSP - finds shortest paths
AcyclicLP - finds longest paths
int source = 2*N;
int sink = 2*N + 1;
// build network
EdgeWeightedDigraph G = new EdgeWeightedDigraph(2*N + 2);
for (int i = 0; i < N; i++) {
double duration = StdIn.readDouble();
G.addEdge(new DirectedEdge(source, i, 0.0));
G.addEdge(new DirectedEdge(i+N, sink, 0.0));
G.addEdge(new DirectedEdge(i, i+N, duration));
// precedence constraints
int M = StdIn.readInt();
for (int j = 0; j < M; j++) {
int precedent = StdIn.readInt();
G.addEdge(new DirectedEdge(N+i, precedent, 0.0));
}
}
// compute longest path
AcyclicLP lp = new AcyclicLP(G, source);
// print results
System.out.println(" job start finish");
System.out.println("--------------------");
for (int i = 0; i < N; i++) {
System.out.printf("%4d %7.1f %7.1f\n", i, lp.distTo(i), lp.distTo(i+N));
}