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

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}}

Output:5.4Explanation: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}}

Output:-1Explanation: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**.

- Only update the shortest path to a vertex
- 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**.

- Only update the shortest path to a vertex

- While doing Dijkstra’s for decreasing shortest paths:
- 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<Vertex> pq` ` ` `= ` `new` `PriorityQueue<Vertex>(` ` ` `new` `Comparator<Vertex>() {` ` ` `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<Integer> adjList;` ` ` `ArrayList<Double> adjWeights;` ` ` `// A constructor which accepts` ` ` `// the id of the vertex` ` ` `public` `Vertex(` `int` `num)` ` ` `{` ` ` `id = num;` ` ` `adjList = ` `new` `ArrayList<Integer>();` ` ` `adjWeights = ` `new` `ArrayList<Double>();` ` ` `}` `}` |

**Output**

5.4

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