Shortest path with one skippable edge - graph

I have this problem: "Shortest path with one skippable edge. Given an edge-weighted digraph, design an E*log(V) algorithm to find a shortest path from s to t where you can change the weight of any one edge to zero. Assume the edge weights are nonnegative."
I don't understand what they want me to do. What does it mean to change the weight to zero? I think that I can change any edge in any shortest path to zero and it will still be the shortest.

First use Dijkstra to find the length S(v) of shortest path from s to v for every vertex v. Then use Dijkstra to find the length T(v) of shortest path from v to t for every vertex v. Then for every edge (v, w) find the sum S(v) + T(w) by using the rules above. Finally, choose the minimum path.
Note: In this approach we nullify the edge (v,w) weight and find the shortest path through (v,w)

The problem is simple.
Suppose that you have a shortest path with one skippable edge, p = v1,...,vi,vi+1,...,vm
and (vi,vi+1) is a skipped edge
Obviously, a path(v1,...,vi) is a shortest path between v1 and vi
and a path(vi+1,...,vm) is a shortest path between vi+1 and vm
Define d(x,y) as the length of the shortest path between node x and node y
you can simply find d(s,x) and d(x,t) for all node x by dijkstra algorithm
and now we have to choose the skipped edge one by one.
In other words, the length of the shortest path with one skippable edge is
min( d(s,u) + d(v,t) ) for all edge (u,v) in the graph
and the time complexity is O(E log V) because of Dijkstra Algorithm

The previous answers seem to suppose that Dijkstra gives the shortest distance from every vertex to every vertex, but this is not the case.
If you execute Dijkstra only once, starting from s, you have the shortest path from s to every vertex.
To find the shortest distance from every vertex to t, it is necessary to execute Dijkstra again starting from t after reversing every edge of the graph.
The complete solution is:
1) Execute Dijkstra on the graph G starting from s to obtain the shortest distance T(v) between s and any v.
2) Reverse all the edges to obtain the reversed graph G'
3) Execute Dijkstra on the graph G' starting from t to obtain the shortest distance R(v) between t and any v.
4) The one to skip is the edge e(v1 --> v2) for which T(v1) + R(v2) is minimum.
5) The path to follow is a concatenation of the shortest path between s and v1 given by the first Dijkstra and the shortest path between v2 and t given by the second Dijkstra.

The existing answers are good and correct, but another idea that is more intuitive to me is to transform the graph and use a layered approach:
Create a copy of the graph G, and call it G'
For each edge (u, v) in G, create an edge (u, v') directed from u (in G) to v' (in G'), of weight 0.
Use any standard shortest path algorithm such as Dijkstra to compute the shortest path from s to t'.

I came across this question when I was doing the Princeton Algorithms course on Coursera. I get the accepted answer, but I came up with an approach that I think should provide the shortest path with one skipped edge from s to any other edge.
We'll use the following class to store weighted, directed edge info:
public class DirectedEdge implements Comparable<DirectedEdge> {
private int from;
private int to;
private double weight;
... boilerplate stuff...
However, we'll 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;
}
}
longest here representing the longest known segment of the shortest known path to the vertex.
The rest is pretty standard Djikstra's with an indexed minimum priority queue and 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] to new SkipPathEdge(null, 0); so we shouldn't ever run into a null parent edge.
I think this should work, unless there's something I'm not thinking of.

Related

How to prune a graph given distance K from a node with jgrapht?

I built a graph using jgrapht API. I have a directed graph. Given a node N, I have to create a subgraph with all connected neighbours with distance K.
So basically given a node, and distance K, I have to prune the graph so that only the connected nodes with distance K remains.
I have an idea to implement it by hand.
I can generate the shortest path between all pairs from the list of nodes.
After that, I can get rid of nodes that are beyond the distance K.
However, this would result in the comparison between all the nodes and would like to know whether there is a better way to do this?
Moreover, wondering jgrapht has an API to do this already.
(I have already looked into the API of jgrapht but have not found any such API)
I assume that distance is defined as the length of the shortest path in a weighted graph, where the length of a path is given by the sum of its edge weights. I also assume that it is only required that all neighbors are within a given maxDistance from input vertex N, and that it is not required that two of those neighbors must also be within maxDistance of each other.
The simplest approach involves:
For a given input vertex N, determine all vertices that are at most maxDistance away from N.
Return an induced subgraph on N plus its (indirect) neighbors that are at most maxDistance units away.
public <V,E> Graph<V, E> getSubgraph(Graph<V,E> graph, V source, double maxDistance){
//Compute a shortest. Optionally we can limit the search to vertices that are maxDistance away
DijkstraShortestPath<V,E> ds = new DijkstraShortestPath<>(graph, maxDistance);
ShortestPathAlgorithm.SingleSourcePaths<V, E> shortestPaths = ds.getPaths(source);
//Collect all neighboring vertices that are at most maxDistance units away
Set<V> neighbors = graph.vertexSet().stream().filter(v -> shortestPaths.getWeight(v) <= maxDistance).collect(Collectors.toSet());
//Return an induced subgraph on those vertices
return new AsSubgraph<>(graph, neighbors);
}

Shortest Path Function (Dijkstra's Algorithm)

I have a data frame composed of a latitude, longitude, node ID, from NodeID, to Node_ID, length. The from and to node columns are my edges. I can only travel on my edges when trying to find the shortest path. I want to be able to go from a node to another node while minimizing my total length traveled. The output should return every node I have to travel through to get to my destination. I have tried many built in packages like cppRouting and igraph, but I can not get anything to work correctly . Any ideas on how to either create a function or how to use any existing functions to accomplish this? Thank you.
Below are the detailed steps used in Dijkstra’s algorithm to find the shortest path from a single source vertex to all other vertices in the given graph.
Algorithm:
1) Create a set sptSet (shortest path tree set) that keeps track of vertices included in shortest path tree, i.e., whose minimum distance from source is calculated and finalized. Initially, this set is empty.
2) Assign a distance value to all vertices in the input graph. Initialize all distance values as INFINITE. Assign distance value as 0 for the source vertex so that it is picked first.
3) While sptSet doesn’t include all vertices
….a) Pick a vertex u which is not there in sptSet and has minimum distance value.
….b) Include u to sptSet.
….c) Update distance value of all adjacent vertices of u. To update the distance values, iterate through all adjacent vertices. For every adjacent vertex v, if sum of distance value of u (from source) and weight of edge u-v, is less than the distance value of v, then update the distance value of v.
Go through the following link: Printing Paths in Dijkstra’s Shortest Path Algorithm

Dijkstra algorithm with min-priority queue

I'm trying to implement the dijkstra algorithm with priority queue, but I can't understand how it works. I read many guide on the web but I can't understand this algorithm at all.
My questions are: What is the priority for each node? I think that it is the weight of the incoming edge with the minimum value, but I'm not sure. Is this true?
Second question, when I extract the root of the queue, how does it work if this node is not adjacency with no one of the visited nodes?
You should use priority queue where the vertex with the shortest distance from the starting vertex will get the highest priority. Initially, all vertices will have the shortest distance of infinity and the starting vertex will have the shortest distance 0.
Start by inserting of all vertices (with its edges) from the graph inside the PQ. Remove vertex from the PQ and explore all its edges. Compare the shortest distances with all adjacent vertices and if any distance is less than the shortest distance on the current vertex, update adjacent vertex shortest distance inside the PQ. Continue while PQ is not empty. Vertices which got no edges will finish with the shortest distance of infinity because it is not possible 'get to them' from the starting vertex. However, they will be still removed from the PQ.
Pseudocode
initialize graph
initialize pq
pq.insertAll(graph.getVertices())
while (pq is not empty) {
vertex = pq.remove()
edges = vertex.getEdges()
for all edges {
destination = edge.getDestination()
newDistance = edge.getLength() + vertex.getDistance()
if (newDistance < destination.getDistance()) {
destination.setShortestDistance(newDistance)
pq.update(destination)
}
}
}
MIT OpenCourseWare Links:
Path problems overview
Dijkstra

The most vital edge on the shortest path

I have this question form the Sedgewick's course on algorithms: "Critical edge. Given an edge-weighted digraph, design an E*log(V) algorithm to find an edge whose removal causes the maximal increase (possibly infinite) in the length of the shortest path from s to t. Assume all of the edge weights are strictly positive. (Hint: compute the shortest path distances d(v) form s to v and consider the reduced costs c′(v,w)=c(v,w)+d(v)−d(w) ≥ 0.)"
I've read on the internet that three (3) guys in 1989 came up with an algorithm of complexity O(E + V*log(V)) what required advanced data structures, and I think it was on a graph (not digraph). If it got three advanced computer scientist to develop this algorithms, is not it too much of a problem for an introductory course? But maybe it is much easier for just O(E*log(V)).
Can you help me to solve it? I don't understand the hint given in the question.
Here is a sketch of an algorithm to find the critical edge on a shortest path, based on Sedgewick's hint.
First, the reduced cost c′(v,w)=c(v,w)+d(v)−d(w) corresponds to the increase in the length of the shortest path from s to w, when going through v just before w. (If v is in the shortest path from s to w then this increase is 0.) (Indeed d(v) is the length of the shortest path from s to v and c(v, w) the cost to go from v to w.)
Suppose the shortest path from s to t is (s, ..., v, t) and that we remove the last edge (v, t). Then the increase in the length of the shortest path from s to t equals the minimum of the c'(u, t) for all in-edges (u, t), with u != v.
Suppose u is such that c'(u, t) is the minimum (still u != v). Then follow the shortest path from s to u backward, until you reach a vertex, say w, belonging to the shortest path from s to t (without any removed edge). The shortest path from s to t is something like (s, ..., w, ..., v, t).
Observe that if you remove any edge between w and t, you will get a maximum increase of c'(u, t) int the shortest path. Indeed, in case one of the edges between w and t is missing, it suffices to go from w to t through the vertex u. On the other hand, note that removing the last edge (v, t) will cause exactly this increase.
Now, just iterate with w what was done with t. Find a vertex x such that c'(x, w) is mininum and x is not on the shortest path. Follow the shortest path from s to x backward until you reach a vertex belonging to the shortest path from s to w.
Once you reach s then you're able to determine which vertex to remove to cause the maximum increase in the lenght of the shortest path.
This is a confusing question, I agree. Here are some my thoughts about it.
The "reduced cost" term and definition is used when reducing the A* search algorithm to Dijkstra's algorithm by replacing the original cost with the reduced cost:
c′(v,w) = c(v,w) - h(v) + h(w) = c(v,w) - (h(v) - h(w)) > 0
The h(v) - h(w) part is a drop of a heuristic function, which should not be more than the edge cost in case of consistent (monotonic) heuristic, thus the reduced cost is still greater than 0 (see slides 14 and 15 here)
It looks like Sedgewick suggests using the original distance function (d(v)) as a consistent heuristic when searching for the new/replacement shortest path in G' which is the same as the original G, but with one removed edge along the original shortest path from s to t. Personally, I don't see how it might help solving the most vital edge problem in O(ElogV) though.
There is also a similar problem: find all downward and upward critical edges in a graph. By definition, decreasing a cost of downward critical edge decreases the overall SP cost. Increasing a cost of upward critical edge increases the overall SP cost. All critical edges can be found in O(ElogV), see ch.8 here. But this does not answer the question what edge is the most critical (causes the max SP increase when removed).
As you noted, the most vital edge problem was solved by Malik, Mittal and Gupta (1989) in
O(E + V*log(V)) time. I have not found the original MMG paper, but this presentation explains it quite well. As far as I can see, it can be solved with a priority queue, no specific data structures required.
Sorry for not actually answering the original question (solution for most vital edge in a digraph using reduced costs), but still hoping that the links and thoughts above might be useful for someone. I would be happy to see the solution meant by Sedgewick.

Finding shortest path contaning exactly one negative edge in a graph

I am given a directed graph with a weight function and a vertex s.
My goal is to find for any other vertex v, the shortest path from s to v that goes through exactly one negative edge. The time complexity of the algorithm should be O(|E| + |V|*log|V|), so guess I need to use Dijkstra's algorithm somehow.
I am guessing that I need to translate my given graph somehow to a new graph with non-negative weights that a shortest path from s to v in this graph will be equivalent to the required shortest path in the given graph.. or maybe I need to modify Dijkstra's algorithm somehow??
I tried to think about it a little, don't have any ideas right now... :(

Resources