Open In App

Number of distinct Shortest Paths from Node 1 to N in a Weighted and Directed Graph

Given a directed and weighted graph of N nodes and M edges, the task is to count the number of shortest length paths between node 1 to N.

Examples:



Input: N = 4, M = 5, edges = {{1, 4, 5}, {1, 2, 4}, {2, 4, 5}, {1, 3, 2}, {3, 4, 3}}
Output: 2
Explanation: The number of shortest path from node 1 to node 4 is 2, having cost 5.



Input: N = 3, M = 2, edges = {{1, 2, 4}, {1, 3, 5}}
Output: 1

Approach: The problem can be solved by the Dijkstra algorithm. Use two arrays, say dist[] to store the shortest distance from the source vertex and paths[] of size N, to store the number of different shortest paths from the source vertex to vertex N. Follow these steps below for the approach.

Below is the implementation of the above approach:




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
const int INF = 1e9;
const int MAXN = 1e5 + 1;
vector<vector<pair<int, int> > > g(MAXN);
vector<int> dist(MAXN);
vector<int> route(MAXN);
 
// Function to count number of shortest
// paths from node 1 to node N
void countDistinctShortestPaths(
    int n, int m, int edges[][3])
{
    // Storing the graph
    for (int i = 0; i < m; ++i) {
        int u = edges[i][0],
            v = edges[i][1],
            c = edges[i][2];
        g[u].push_back({ v, c });
    }
 
    // Initializing dis array to a
    // large value
    for (int i = 2; i <= n; ++i) {
        dist[i] = INF;
    }
 
    // Initialize a priority queue
    priority_queue<pair<int, int>,
                   vector<pair<int, int> >,
                   greater<pair<int, int> > >
        pq;
    pq.push({ 0, 1 });
 
    // Base Cases
    dist[1] = 0;
    route[1] = 1;
 
    // Loop while priority queue is
    // not empty
    while (!pq.empty()) {
        int d = pq.top().first;
        int u = pq.top().second;
        pq.pop();
 
        // if d is greater than distance
        // of the node
        if (d > dist[u])
            continue;
 
        // Traversing all its neighbours
        for (auto e : g[u]) {
            int v = e.first;
            int c = e.second;
            if (c + d > dist[v])
                continue;
 
            // Path found of same distance
            if (c + d == dist[v]) {
                route[v] += route[u];
            }
 
            // New path found for lesser
            // distance
            if (c + d < dist[v]) {
                dist[v] = c + d;
                route[v] = route[u];
 
                // Pushing in priority
                // queue
                pq.push({ dist[v], v });
            }
        }
    }
}
 
// Driver Code
int main()
{
    // Given Input
    int n = 4;
    int m = 5;
    int edges[m][3] = { { 1, 4, 5 },
                        { 1, 2, 4 },
                        { 2, 4, 5 },
                        { 1, 3, 2 },
                        { 3, 4, 3 } };
 
    // Function Call
    countDistinctShortestPaths(n, m, edges);
    cout << route[n] << endl;
 
    return 0;
}




// Java program for the above approach
 
import java.io.*;
import java.util.*;
 
class GFG {
 
    // Function to count number of shortest paths from node
    // 1 to node N
    static void countDistinctShortestPaths(int n, int m,
                                           int[][] edges)
    {
        List<int[]>[] g = new List[n + 1];
        int[] dist = new int[n + 1];
        int[] route = new int[n + 1];
 
        // Storing the graph
        for (int i = 0; i < m; i++) {
            int u = edges[i][0];
            int v = edges[i][1];
            int c = edges[i][2];
            if (g[u] == null) {
                g[u] = new ArrayList<int[]>();
            }
            g[u].add(new int[] { v, c });
        }
 
        // Initializing dis array to a large value
        Arrays.fill(dist, Integer.MAX_VALUE);
 
        // Base Cases
        dist[1] = 0;
        route[1] = 1;
 
        // Loop while priority queue is not empty
        PriorityQueue<int[]> pq = new PriorityQueue<>(
            Comparator.comparingInt(a -> a[0]));
        pq.add(new int[] { 0, 1 });
        while (!pq.isEmpty()) {
            int[] poll = pq.poll();
            int d = poll[0];
            int u = poll[1];
 
            // if d is greater than distance of the node
            if (d > dist[u])
                continue;
 
            // Traversing all its neighbours
            if (g[u] != null) {
                for (int i = 0; i < g[u].size(); i++) {
                    int[] edge = g[u].get(i);
                    int v = edge[0];
                    int c = edge[1];
                    if (c + d > dist[v])
                        continue;
 
                    // Path found of same distance
                    if (c + d == dist[v]) {
                        route[v] += route[u];
                    }
 
                    // New path found for lesser distance
                    if (c + d < dist[v]) {
                        dist[v] = c + d;
                        route[v] = route[u];
 
                        // Pushing in priority queue
                        pq.add(new int[] { dist[v], v });
                    }
                }
            }
        }
        System.out.println(route[n]);
    }
 
    public static void main(String[] args)
    {
        // Given Input
        int n = 4;
        int m = 5;
        int[][] edges = { { 1, 4, 5 },
                          { 1, 2, 4 },
                          { 2, 4, 5 },
                          { 1, 3, 2 },
                          { 3, 4, 3 } };
 
        // Function Call
        countDistinctShortestPaths(n, m, edges);
    }
}
 
// This code is contributed by karthik.




# Python3 program for the above approach
from queue import PriorityQueue
from collections import defaultdict
import sys
 
INF = int(1e9)
MAXN = int(1e5 + 1)
 
# A function to count the number of shortest paths from node 1 to node N
def countDistinctShortestPaths(n, m, edges):
    # Storing the graph using adjacency list
    g = defaultdict(list)
    for i in range(m):
        u, v, c = edges[i]
        g[u].append((v, c))
 
    # Initializing the distance array to a large value
    dist = [INF] * (n + 1)
 
    # Initializing the count array to store the number of shortest paths
    route = [0] * (n + 1)
 
    # Base Cases
    dist[1] = 0
    route[1] = 1
 
    # Initialize a priority queue
    pq = PriorityQueue()
    pq.put((0, 1))
 
    # Loop while priority queue is not empty
    while not pq.empty():
        d, u = pq.get()
 
        # if d is greater than distance of the node
        if d > dist[u]:
            continue
 
        # Traversing all its neighbours
        for v, c in g[u]:
            if c + d > dist[v]:
                continue
 
            # Path found of same distance
            if c + d == dist[v]:
                route[v] += route[u]
 
            # New path found for lesser distance
            if c + d < dist[v]:
                dist[v] = c + d
                route[v] = route[u]
 
                # Pushing in priority queue
                pq.put((dist[v], v))
 
    # Return the number of shortest paths from node 1 to node N
    return route[n]
 
# Driver Code
if __name__ == "__main__":
    # Given Input
    n = 4
    m = 5
    edges = [(1, 4, 5),
             (1, 2, 4),
             (2, 4, 5),
             (1, 3, 2),
             (3, 4, 3)]
 
    # Function Call
    result = countDistinctShortestPaths(n, m, edges)
    print(result)




using System;
using System.Collections.Generic;
 
class ShortestPaths
{
    const int INF = int.MaxValue;
    const int MAXN = 100001;
    static List<List<Tuple<int, int>>> g = new List<List<Tuple<int, int>>>(MAXN);
    static List<int> dist = new List<int>(MAXN);
    static List<int> route = new List<int>(MAXN);
 
    static void CountDistinctShortestPaths(int n, int m, int[,] edges)
    {
        // Storing the graph
        for (int i = 0; i < n + 1; ++i)
        {
            g.Add(new List<Tuple<int, int>>());
            dist.Add(INF);
            route.Add(0);
        }
 
        for (int i = 0; i < m; ++i)
        {
            int u = edges[i, 0];
            int v = edges[i, 1];
            int c = edges[i, 2];
            g[u].Add(new Tuple<int, int>(v, c));
        }
 
        // Initialize a priority queue
        var pq = new SortedSet<Tuple<int, int>>(Comparer<Tuple<int, int>>.Create((x, y) =>
        {
            int compare = x.Item1.CompareTo(y.Item1);
            return compare == 0 ? x.Item2.CompareTo(y.Item2) : compare;
        }));
 
        pq.Add(new Tuple<int, int>(0, 1));
 
        // Base Cases
        dist[1] = 0;
        route[1] = 1;
 
        // Loop while priority queue is not empty
        while (pq.Count > 0)
        {
            var top = pq.Min;
            pq.Remove(top);
 
            int d = top.Item1;
            int u = top.Item2;
 
            // if d is greater than distance of the node
            if (d > dist[u])
                continue;
 
            // Traversing all its neighbours
            foreach (var e in g[u])
            {
                int v = e.Item1;
                int c = e.Item2;
                if (c + d > dist[v])
                    continue;
 
                // Path found of the same distance
                if (c + d == dist[v])
                {
                    route[v] += route[u];
                }
 
                // New path found for lesser distance
                if (c + d < dist[v])
                {
                    dist[v] = c + d;
                    route[v] = route[u];
 
                    // Pushing in priority queue
                    pq.Add(new Tuple<int, int>(dist[v], v));
                }
            }
        }
    }
 
    // Driver Code
    static void Main()
    {
        // Given Input
        int n = 4;
        int m = 5;
        int[,] edges = { { 1, 4, 5 },
                         { 1, 2, 4 },
                         { 2, 4, 5 },
                         { 1, 3, 2 },
                         { 3, 4, 3 } };
 
        // Function Call
        CountDistinctShortestPaths(n, m, edges);
        Console.WriteLine(route[n]);
    }
}




// Function to count number of shortest
// paths from node 1 to node N
function countDistinctShortestPaths(n, m, edges) {
    let g = [];
    let dist = [];
    let route = [];
 
    // Storing the graph
    for (let i = 0; i < m; i++) {
        let u = edges[i][0];
        let v = edges[i][1];
        let c = edges[i][2];
        if (!g[u]) {
            g[u] = [];
        }
        g[u].push([v, c]);
    }
 
    // Initializing dis array to a
    // large value
    for (let i = 2; i <= n; i++) {
        dist[i] = Number.MAX_SAFE_INTEGER;
    }
 
    // Base Cases
    dist[1] = 0;
    route[1] = 1;
 
    // Loop while priority queue is
    // not empty
    let pq = [];
    pq.push([0, 1]);
    while (pq.length > 0) {
        let d = pq[0][0];
        let u = pq[0][1];
        pq.shift();
 
        // if d is greater than distance
        // of the node
        if (d > dist[u]) continue;
 
        // Traversing all its neighbours
        if (g[u]) {
            for (let i = 0; i < g[u].length; i++) {
                let v = g[u][i][0];
                let c = g[u][i][1];
                if (c + d > dist[v]) continue;
 
                // Path found of same distance
                if (c + d === dist[v]) {
                    route[v] += route[u];
                }
 
                // New path found for lesser
                // distance
                if (c + d < dist[v]) {
                    dist[v] = c + d;
                    route[v] = route[u];
 
                    // Pushing in priority
                    // queue
                    pq.push([dist[v], v]);
                }
            }
        }
    }
    console.log(route[n]);
}
 
// Given Input
let n = 4;
let m = 5;
let edges = [[1, 4, 5],
    [1, 2, 4],
    [2, 4, 5],
    [1, 3, 2],
    [3, 4, 3]
];
 
// Function Call
countDistinctShortestPaths(n, m, edges);

Output
2

Time Complexity: O(MLogN)
Auxiliary Space: O(N)


Article Tags :