# Monotonic shortest path from source to destination in Directed Weighted Graph

• Last Updated : 03 Aug, 2022

Given a weighted directed graph with N vertices and M edges, a source src and a destination target, the task is to find the shortest monotonic path (monotonically increasing or decreasing) from the source to the destination. Output -1 if no monotonic path is possible.

Note: All weights are non-negative

Examples:

Input: N = 6, M = 9, src = 1, target = 2
edges = {{1, 3, 1.1}, {1, 5, 2}, {1, 6, 3.3}, {2, 5, 2.7},
{3, 4, 2}, {3, 5, 1.1}, {4, 2, 2.3}, {5, 6, 2.4}, {6, 2, 3}} Graph for first example

Output: 5.4
Explanation: There are three monotonic paths in the graph
that originate from vertex 1, which are 1 – 6 – 2 because it is strictly increasing,
and 1 – 3 – 4 – 2, and 1 – 5 – 6 – 2 since both are strictly decreasing.
The shortest one of these paths is 1 – 3 – 4 – 2,
which has a sum of weights equal to 1.1 + 2 + 2.3 = 5.4,
So the output is 5.4.

Input: N = 5, M = 5, src = 1, target = 5
edges = {{1, 2, 2.3}, {1, 3, 3.1}, {2, 3, 3.7}, {3, 4, 1.9}, {4, 5, 2.1}} Graph for second example

Output: -1
Explanation: No monotonic path exists from vertex 1 to vertex 5.

Approach: To solve the problem follow the below idea:

Run Dijkstra’s algorithm twice: one for increasing shortest paths and another for decreasing shortest paths, and take the shorter path of the two results.

Follow the given steps to solve the problem:

• Run Dijkstra’s algorithm twice for both increasing and decreasing paths.
• While doing Dijkstra’s for decreasing shortest paths:
• Only update the shortest path to a vertex v from vertex u if the weight of the edge from u to v is less than the edge on the shortest path directed towards u
• Similarly for the increasing shortest paths:
• Only update the shortest path to a vertex v from u, if the edge from u to v is greater than the edge on the shortest path directed towards u.
• If the destination vertex has not yet been reached, then no valid shortest path exists.
• If both passes of Dijkstra’s on increasing and decreasing shortest paths result in no valid paths, then return -1.

Below is the implementation of the above approach.

## Java

 `import` `java.io.*;` `import` `java.util.*;`   `// Finds the monotonic shortest path` `// using Dijkstra's algorithm` `class` `Main {` `    ``public` `static` `void` `main(String[] args)` `    ``{` `        ``int` `N = ``6``;` `        ``int` `M = ``9``;`   `        ``// Create an array of vertices` `        ``Vertex[] vertices = ``new` `Vertex[N + ``1``];`   `        ``// Create instances of each vertex from 1 to N` `        ``for` `(``int` `i = ``1``; i <= N; i++)` `            ``vertices[i] = ``new` `Vertex(i);`   `        ``vertices[``1``].adjList.add(``3``);` `        ``vertices[``1``].adjWeights.add(``1.1``);`   `        ``vertices[``1``].adjList.add(``5``);` `        ``vertices[``1``].adjWeights.add(``2.0``);`   `        ``vertices[``1``].adjList.add(``6``);` `        ``vertices[``1``].adjWeights.add(``3.3``);`   `        ``vertices[``2``].adjList.add(``5``);` `        ``vertices[``2``].adjWeights.add(``2.7``);`   `        ``vertices[``3``].adjList.add(``4``);` `        ``vertices[``3``].adjWeights.add(``2.0``);`   `        ``vertices[``3``].adjList.add(``5``);` `        ``vertices[``3``].adjWeights.add(``1.1``);`   `        ``vertices[``4``].adjList.add(``2``);` `        ``vertices[``4``].adjWeights.add(``2.3``);`   `        ``vertices[``5``].adjList.add(``6``);` `        ``vertices[``5``].adjWeights.add(``2.4``);`   `        ``vertices[``6``].adjList.add(``2``);` `        ``vertices[``6``].adjWeights.add(``3.0``);`   `        ``// Source and destination vertices` `        ``int` `src = ``1``;` `        ``int` `target = ``2``;` `        ``System.out.println(` `            ``shortestPath(vertices, N, src, target));` `    ``}`   `    ``public` `static` `double` `shortestPath(Vertex vertices[],` `                                      ``int` `N, ``int` `source,` `                                      ``int` `destination)` `    ``{` `        ``// Stores distance from source and edge` `        ``// on the shortest path from source` `        ``double``[] distTo = ``new` `double``[N + ``1``];` `        ``double``[] edgeTo = ``new` `double``[N + ``1``];`   `        ``// Set initial distance from source` `        ``// to the highest value` `        ``for` `(``int` `i = ``1``; i <= N; i++)` `            ``distTo[i] = Double.MAX_VALUE;`   `        ``// Monotonic decreasing pass of dijkstras` `        ``distTo = ``0.0``;` `        ``edgeTo = Double.MAX_VALUE;`   `        ``PriorityQueue pq` `            ``= ``new` `PriorityQueue(` `                ``new` `Comparator() {` `                    ``public` `int` `compare(Vertex a, Vertex b)` `                    ``{` `                        ``return` `Double.compare(distTo[a.id],` `                                              ``distTo[b.id]);` `                    ``}` `                ``});`   `        ``// Add the initial source vertex` `        ``// into the priority queue` `        ``pq.add(vertices);`   `        ``while` `(!pq.isEmpty()) {`   `            ``// Take the vertex with the closest` `            ``// current distance from source` `            ``Vertex closest = pq.remove();`   `            ``for` `(``int` `i = ``0``; i < closest.adjList.size();` `                 ``i++) {`   `                ``// Checks if the edges are decreasing and` `                ``// whether the current directed edge will` `                ``// create a shorter path` `                ``if` `(closest.adjWeights.get(i)` `                        ``< edgeTo[closest.id]` `                    ``&& distTo[closest.id]` `                               ``+ closest.adjWeights.get(i)` `                           ``< distTo[closest.adjList.get(` `                                 ``i)]) {` `                    ``edgeTo[closest.adjList.get(i)]` `                        ``= closest.adjWeights.get(i);` `                    ``distTo[closest.adjList.get(i)]` `                        ``= closest.adjWeights.get(i)` `                          ``+ distTo[closest.id];` `                    ``pq.add(` `                        ``vertices[closest.adjList.get(i)]);` `                ``}` `            ``}` `        ``}`   `        ``// Store the result of the first pass of dijkstras` `        ``double` `firstPass = distTo[destination];`   `        ``// Monotonic increasing pass of dijkstras` `        ``for` `(``int` `i = ``1``; i <= N; i++)` `            ``distTo[i] = Double.MAX_VALUE;` `        ``distTo = ``0.0``;` `        ``edgeTo = ``0.0``;`   `        ``// Add the initial source vertex` `        ``// into the priority queue` `        ``pq.add(vertices);`   `        ``while` `(!pq.isEmpty()) {`   `            ``// Take the vertex with the closest current` `            ``// distance from source` `            ``Vertex closest = pq.remove();`   `            ``for` `(``int` `i = ``0``; i < closest.adjList.size();` `                 ``i++) {`   `                ``// Checks if the edges are increasing and` `                ``// whether the current directed edge will` `                ``// create a shorter path` `                ``if` `(closest.adjWeights.get(i)` `                        ``> edgeTo[closest.id]` `                    ``&& distTo[closest.id]` `                               ``+ closest.adjWeights.get(i)` `                           ``< distTo[closest.adjList.get(` `                                 ``i)]) {` `                    ``edgeTo[closest.adjList.get(i)]` `                        ``= closest.adjWeights.get(i);` `                    ``distTo[closest.adjList.get(i)]` `                        ``= closest.adjWeights.get(i)` `                          ``+ distTo[closest.id];` `                    ``pq.add(` `                        ``vertices[closest.adjList.get(i)]);` `                ``}` `            ``}` `        ``}`   `        ``// Store the result of the second pass of Dijkstras` `        ``double` `secondPass = distTo[destination];`   `        ``if` `(firstPass == Double.MAX_VALUE` `            ``&& secondPass == Double.MAX_VALUE)` `            ``return` `-``1``;` `        ``return` `Math.min(firstPass, secondPass);` `    ``}` `}`   `// Represents a vertex in the graph` `// id stores the vertex number of the vertex instance` `// adjList stores the id's of adjacent vertices` `// adjWeights stores the weights of adjacent vertices with` `// the same indexing as adjList` `class` `Vertex {` `    ``int` `id;` `    ``ArrayList adjList;` `    ``ArrayList adjWeights;`   `    ``// A constructor which accepts` `    ``// the id of the vertex` `    ``public` `Vertex(``int` `num)` `    ``{` `        ``id = num;` `        ``adjList = ``new` `ArrayList();` `        ``adjWeights = ``new` `ArrayList();` `    ``}` `}`

Output

`5.4`

Time Complexity: O(N log(N) + M)
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up
Recommended Articles
Page :