I came across this question when I was taking Princeton's Algorithm course on Coursera. I got the accepted answer, but I suggested an approach that I think should provide the shortest path with one missing edge from s to any other edge.
We will use the following class to store weighted information about directed edges:
public class DirectedEdge implements Comparable<DirectedEdge> { private int from; private int to; private double weight; ... boilerplate stuff...
However, we will also add a decorator class:
public static class SkipPathEdge { DirectedEdge directedEdge; double longest; public SkipPathEdge(DirectedEdge directedEdge, double longest) { this.directedEdge = directedEdge; this.longest = longest; } }
the longest here, representing the longest known segment of the shortest known path to the top.
The rest is a fairly standard Djikstra with an indexed queue with minimal priority and that’s all, but with a slightly modified relaxation method:
private void relax(EdgeWeightedDigraph G, int e) { SkipPathEdge parentEdge = edgeTo[e]; for (DirectedEdge edge : G.adj(e)) { double longest = Math.max(parentEdge.longest, edge.getWeight()); double adjustment = longest - parentEdge.longest; SkipPathEdge childEdge = new SkipPathEdge(edge, longest); int from = edge.getFrom(), to = edge.getTo(); if (distTo[to] > distTo[from] + edge.getWeight() - adjustment) { distTo[to] = distTo[from] + edge.getWeight() - adjustment; edgeTo[to] = childEdge; if (minPQ.contains(to)) { minPQ.changeKey(to, distTo[to]); } else { minPQ.addKey(to, distTo[to]); } } } }
And to clarify, we initialize edgeTo [s] as new SkipPathEdge(null, 0); so that we never have to deal with a null parent edge.
I think this should work if there isn’t something that I don’t think about.
source share