Number of Ways to Reach Destination in Shortest Time
Last Updated : 18 Nov, 2025
Given an undirected weighted graph containing V vertices from 0 to V-1 represented as an adjacency list adj[][], where each adj[u] contains pairs [v, t] indicating there is an edge between nodes u and v such that it takes travel time of t to reach from u to v or v to u.
Find the number of distinct paths to reach(V-1)th node from 0th node in minimum amount of time.
We start a DFS from node 0 and explore every possible path to the destination n-1. While exploring, we track the total time taken so far. If at any point this time exceeds the current best (shortest) time, we stop exploring that path because we already know a faster route exists through some other path. If we reach the destination, we check whether this path is faster than all previous ones; if it is, we update the shortest time and reset the count of ways to 1. If it matches the current shortest time, we simply increase the count. During DFS, we mark nodes as visited to avoid revisiting them in the same path, and unmark them on backtracking so other paths can reuse the node. In this way, we systematically try all valid paths, prune the ones that are guaranteed to be worse, and finally count how many distinct paths achieve the minimum possible time.
C++
//Driver Code Starts#include<iostream>#include<vector>#include<climits>usingnamespacestd;//Driver Code Endsvoiddfs(intnode,intcurrentTime,vector<vector<pair<int,int>>>&adj,vector<int>&vis,intV,int&shortest,int&ways){// prune: no need to go furtherif(currentTime>shortest)return;if(node==V-1){// if time to reach the node is new minimum// change the number of ways to 1(for current path)if(currentTime<shortest){shortest=currentTime;ways=1;}// increment the number of ways to // reach the node in shortest timeelseif(currentTime==shortest){ways++;}return;}vis[node]=1;for(auto&p:adj[node]){intnext=p.first;intwt=p.second;if(vis[next]==0){dfs(next,currentTime+wt,adj,vis,V,shortest,ways);}}// backtracking and marking // node as unvisitedvis[node]=0;}intcountPaths(vector<vector<pair<int,int>>>&adj){intV=adj.size();vector<int>vis(V,0);// to store the shortest time // needed to reach node V-1 from 0intshortest=INT_MAX;// number of ways to reach// node V-1 in shortest timeintways=0;dfs(0,0,adj,vis,V,shortest,ways);returnways;}//Driver Code StartsvoidaddEdge(vector<vector<pair<int,int>>>&adj,intu,intv,intwt){adj[u].push_back({v,wt});adj[v].push_back({u,wt});}intmain(){intV=4;vector<vector<pair<int,int>>>adj(V);addEdge(adj,0,1,2);addEdge(adj,0,3,5);addEdge(adj,1,2,3);addEdge(adj,1,3,3);addEdge(adj,2,3,4);cout<<countPaths(adj);}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.ArrayList;importjava.util.Arrays;classGFG{//Driver Code Endsstaticvoiddfs(intnode,intcurrentTime,ArrayList<ArrayList<int[]>>adj,int[]vis,intV,int[]shortest,int[]ways){// prune: no need to go furtherif(currentTime>shortest[0])return;if(node==V-1){// if time to reach the node is new minimum// change the number of ways to 1(for current path)if(currentTime<shortest[0]){shortest[0]=currentTime;ways[0]=1;}// increment the number of ways to // reach the node in shortest timeelseif(currentTime==shortest[0]){ways[0]++;}return;}vis[node]=1;for(int[]p:adj.get(node)){intnext=p[0];intwt=p[1];if(vis[next]==0){dfs(next,currentTime+wt,adj,vis,V,shortest,ways);}}// backtracking and marking // node as unvisitedvis[node]=0;}staticintcountPaths(ArrayList<ArrayList<int[]>>adj){intV=adj.size();int[]vis=newint[V];// to store the shortest time // needed to reach node V-1 from 0int[]shortest=newint[]{Integer.MAX_VALUE};// number of ways to reach// node V-1 in shortest timeint[]ways=newint[]{0};dfs(0,0,adj,vis,V,shortest,ways);returnways[0];}//Driver Code StartsstaticvoidaddEdge(ArrayList<ArrayList<int[]>>adj,intu,intv,intwt){adj.get(u).add(newint[]{v,wt});adj.get(v).add(newint[]{u,wt});}publicstaticvoidmain(String[]args){intV=4;ArrayList<ArrayList<int[]>>adj=newArrayList<>();for(inti=0;i<V;i++)adj.add(newArrayList<>());addEdge(adj,0,1,2);addEdge(adj,0,3,5);addEdge(adj,1,2,3);addEdge(adj,1,3,3);addEdge(adj,2,3,4);System.out.println(countPaths(adj));}}//Driver Code Ends
Python
defdfs(node,currentTime,adj,vis,V,shortest,ways):# prune: no need to go furtherifcurrentTime>shortest[0]:returnifnode==V-1:# if time to reach the node is new minimum# change the number of ways to 1(for current path)ifcurrentTime<shortest[0]:shortest[0]=currentTimeways[0]=1# increment the number of ways to # reach the node in shortest timeelifcurrentTime==shortest[0]:ways[0]+=1returnvis[node]=1forpinadj[node]:next=p[0]wt=p[1]ifvis[next]==0:dfs(next,currentTime+wt,adj,vis,V,shortest,ways)# backtracking and marking # node as unvisitedvis[node]=0defcountPaths(adj):V=len(adj)vis=[0]*V# to store the shortest time # needed to reach node V-1 from 0shortest=[10**18]# number of ways to reach# node V-1 in shortest timeways=[0]dfs(0,0,adj,vis,V,shortest,ways)returnways[0]#Driver Code StartsdefaddEdge(adj,u,v,wt):adj[u].append((v,wt))adj[v].append((u,wt))if__name__=="__main__":V=4adj=[[]for_inrange(V)]addEdge(adj,0,1,2)addEdge(adj,0,3,5)addEdge(adj,1,2,3)addEdge(adj,1,3,3)addEdge(adj,2,3,4)print(countPaths(adj))#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;classGFG{//Driver Code Endsstaticvoiddfs(intnode,intcurrentTime,List<List<int[]>>adj,int[]vis,intV,int[]shortest,int[]ways){// prune: no need to go furtherif(currentTime>shortest[0])return;if(node==V-1){// if time to reach the node is new minimum// change the number of ways to 1(for current path)if(currentTime<shortest[0]){shortest[0]=currentTime;ways[0]=1;}// increment the number of ways to // reach the node in shortest timeelseif(currentTime==shortest[0]){ways[0]++;}return;}vis[node]=1;foreach(varpinadj[node]){intnext=p[0];intwt=p[1];if(vis[next]==0){dfs(next,currentTime+wt,adj,vis,V,shortest,ways);}}// backtracking and marking // node as unvisitedvis[node]=0;}staticintcountPaths(List<List<int[]>>adj){intV=adj.Count;int[]vis=newint[V];// to store the shortest time // needed to reach node V-1 from 0int[]shortest=newint[]{int.MaxValue};// number of ways to reach// node V-1 in shortest timeint[]ways=newint[]{0};dfs(0,0,adj,vis,V,shortest,ways);returnways[0];}//Driver Code StartsstaticvoidaddEdge(List<List<int[]>>adj,intu,intv,intwt){adj[u].Add(newint[]{v,wt});adj[v].Add(newint[]{u,wt});}staticvoidMain(){intV=4;varadj=newList<List<int[]>>();for(inti=0;i<V;i++)adj.Add(newList<int[]>());addEdge(adj,0,1,2);addEdge(adj,0,3,5);addEdge(adj,1,2,3);addEdge(adj,1,3,3);addEdge(adj,2,3,4);Console.WriteLine(countPaths(adj));}}//Driver Code Ends
JavaScript
functiondfs(node,currentTime,adj,vis,V,shortest,ways){// prune: no need to go furtherif(currentTime>shortest[0])return;if(node===V-1){// if time to reach the node is new minimum// change the number of ways to 1(for current path)if(currentTime<shortest[0]){shortest[0]=currentTime;ways[0]=1;}// increment the number of ways to // reach the node in shortest timeelseif(currentTime===shortest[0]){ways[0]++;}return;}vis[node]=1;for(letpofadj[node]){letnext=p[0];letwt=p[1];if(vis[next]===0){dfs(next,currentTime+wt,adj,vis,V,shortest,ways);}}// backtracking and marking // node as unvisitedvis[node]=0;}functioncountPaths(adj){letV=adj.length;letvis=Array(V).fill(0);// to store the shortest time // needed to reach node V-1 from 0letshortest=[Number.MAX_SAFE_INTEGER];// number of ways to reach// node V-1 in shortest timeletways=[0];dfs(0,0,adj,vis,V,shortest,ways);returnways[0];}//Driver Code StartsfunctionaddEdge(adj,u,v,wt){adj[u].push([v,wt]);adj[v].push([u,wt]);}// Driver codeletV=4;letadj=Array.from({length:V},()=>[]);addEdge(adj,0,1,2);addEdge(adj,0,3,5);addEdge(adj,1,2,3);addEdge(adj,1,3,3);addEdge(adj,2,3,4);console.log(countPaths(adj));//Driver Code Ends
Output
2
Time Complexity: O(KV), where K is the average branching factor of the vertices in the graph and V is the number of vertices in the graph. Space Complexity: O(V) where V is the number of vertices in the graph.
[Expected Approach] Using Dijkstra's Algorithm - O(V+ E log E) Time and O(V+E) Space
Since, we need to find distinct shortest paths from source to destination and the graph contains positive edge weights, we can use dijkstra's algorithm. Here, we use Dijkstra’s algorithm to track both the shortest time to each node and the number of ways to reach that node in minimum time. We maintain a minTime[] array for the best time to reach each node and a paths[] array for how many shortest paths lead there. As we relax edges, if we find a strictly better time, we update both the time and the path count. If we find an equal time, we add the number of paths from the current node. By the end, paths[V-1] gives the total number of shortest paths to the destination.
C++
//Driver Code Starts#include<iostream>#include<vector>#include<queue>#include<climits>usingnamespacestd;//Driver Code EndsintcountPaths(vector<vector<pair<int,int>>>&adj){intV=adj.size();// min time to reach a node from src(0)vector<int>minTime(V,INT_MAX);// number of ways to reach a node // from src(0) with minimum costvector<int>paths(V,0);minTime[0]=0;paths[0]=1;// sort nodes by time taken to reach // them from src in ascending orderpriority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>pq;pq.push({0,0});while(!pq.empty()){autotop=pq.top();pq.pop();intnode=top.second;intcurrentTime=top.first;if(currentTime>minTime[node])continue;for(auto&next:adj[node]){intnextNode=next.first;intnextTime=next.second;intnewTime=nextTime+currentTime;// if newTime is less than stored value// then update paths and timeif(newTime<minTime[nextNode]){minTime[nextNode]=newTime;paths[nextNode]=paths[node];pq.push({newTime,nextNode});}elseif(newTime==minTime[nextNode]){// increment the count of // paths if time is samepaths[nextNode]=(paths[nextNode]+paths[node]);}}}// return number of paths to reach // dest from src in min timereturnpaths[V-1];}//Driver Code StartsvoidaddEdge(vector<vector<pair<int,int>>>&adj,intu,intv,intwt){adj[u].push_back({v,wt});adj[v].push_back({u,wt});}intmain(){intV=4;vector<vector<pair<int,int>>>adj(V);addEdge(adj,0,1,2);addEdge(adj,0,3,5);addEdge(adj,1,2,3);addEdge(adj,1,3,3);addEdge(adj,2,3,4);cout<<countPaths(adj);}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.ArrayList;importjava.util.Arrays;importjava.util.PriorityQueue;classGFG{//Driver Code EndsstaticintcountPaths(ArrayList<ArrayList<int[]>>adj){intV=adj.size();// min time to reach a node from src(0)int[]minTime=newint[V];// number of ways to reach a node // from src(0) with minimum costint[]paths=newint[V];Arrays.fill(minTime,Integer.MAX_VALUE);minTime[0]=0;paths[0]=1;// sort nodes by time taken to reach // them from src in ascending orderPriorityQueue<int[]>pq=newPriorityQueue<>((a,b)->a[0]-b[0]);pq.offer(newint[]{0,0});while(!pq.isEmpty()){int[]top=pq.poll();intnode=(int)top[1];intcurrentTime=top[0];if(currentTime>minTime[node])continue;for(int[]next:adj.get(node)){intnextNode=(int)next[0];intnextTime=next[1];intnewTime=nextTime+currentTime;// if newTime is less than stored value// then update paths and timeif(newTime<minTime[nextNode]){minTime[nextNode]=newTime;paths[nextNode]=paths[node];pq.offer(newint[]{newTime,nextNode});}elseif(newTime==minTime[nextNode]){// increment the count of // paths if time is samepaths[nextNode]=(paths[nextNode]+paths[node]);}}}// return number of paths to reach // dest from src in min timereturnpaths[V-1];}//Driver Code StartsstaticvoidaddEdge(ArrayList<ArrayList<int[]>>adj,intu,intv,intwt){// directed graphadj.get(u).add(newint[]{v,wt});adj.get(v).add(newint[]{u,wt});}publicstaticvoidmain(String[]args){intV=4;ArrayList<ArrayList<int[]>>adj=newArrayList<>();for(inti=0;i<V;i++){adj.add(newArrayList<>());}addEdge(adj,0,1,2);addEdge(adj,0,3,5);addEdge(adj,1,2,3);addEdge(adj,1,3,3);addEdge(adj,2,3,4);System.out.println(countPaths(adj));}}//Driver Code Ends
Python
#Driver Code Startsimportheapq#Driver Code EndsdefcountPaths(adj):V=len(adj)# min time to reach a node from src(0)minTime=[float('inf')]*V# number of ways to reach a node # from src(0) with minimum costpaths=[0]*VminTime[0]=0paths[0]=1# sort nodes by time taken to reach # them from src in ascending orderpq=[(0,0)]# (time, node)whilepq:currentTime,node=heapq.heappop(pq)ifcurrentTime>minTime[node]:continuefornextNode,nextTimeinadj[node]:newTime=nextTime+currentTime# if newTime is less than stored value# then update paths and timeifnewTime<minTime[nextNode]:minTime[nextNode]=newTimepaths[nextNode]=paths[node]heapq.heappush(pq,(newTime,nextNode))elifnewTime==minTime[nextNode]:# increment the count of # paths if time is samepaths[nextNode]=(paths[nextNode]+paths[node])# return number of paths to reach # dest from src in min timereturnpaths[V-1]#Driver Code StartsdefaddEdge(adj,u,v,wt):adj[u].append((v,wt))adj[v].append((u,wt))if__name__=="__main__":V=4adj=[[]for_inrange(V)]addEdge(adj,0,1,2)addEdge(adj,0,3,5)addEdge(adj,1,2,3)addEdge(adj,1,3,3)addEdge(adj,2,3,4)print(countPaths(adj))#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;classGFG{//Driver Code EndsstaticintcountPaths(List<List<int[]>>adj){intV=adj.Count;// min time to reach a node from src(0)int[]minTime=newint[V];// number of ways to reach a node // from src(0) with minimum costint[]paths=newint[V];for(inti=0;i<V;i++)minTime[i]=int.MaxValue;minTime[0]=0;paths[0]=1;// sort nodes by time taken to reach // them from src in ascending ordervarpq=newSortedSet<Tuple<int,int>>(Comparer<Tuple<int,int>>.Create((a,b)=>a.Item1!=b.Item1?a.Item1-b.Item1:a.Item2-b.Item2));pq.Add(Tuple.Create(0,0));while(pq.Count>0){vartop=pq.Min;pq.Remove(top);intnode=top.Item2;intcurrentTime=top.Item1;if(currentTime>minTime[node])continue;foreach(varnextinadj[node]){intnextNode=next[0];intnextTime=next[1];intnewTime=nextTime+currentTime;// if newTime is less than stored value// then update paths and timeif(newTime<minTime[nextNode]){minTime[nextNode]=newTime;paths[nextNode]=paths[node];pq.Add(Tuple.Create(newTime,nextNode));}elseif(newTime==minTime[nextNode]){// increment the count of // paths if time is samepaths[nextNode]=(paths[nextNode]+paths[node]);}}}// return number of paths to reach // dest from src in min timereturnpaths[V-1];}//Driver Code StartsstaticvoidaddEdge(List<List<int[]>>adj,intu,intv,intwt){adj[u].Add(newint[]{v,wt});adj[v].Add(newint[]{u,wt});}staticvoidMain(){intV=4;varadj=newList<List<int[]>>();for(inti=0;i<V;i++)adj.Add(newList<int[]>());addEdge(adj,0,1,2);addEdge(adj,0,3,5);addEdge(adj,1,2,3);addEdge(adj,1,3,3);addEdge(adj,2,3,4);Console.WriteLine(countPaths(adj));}}//Driver Code Ends
JavaScript
functioncountPaths(adj){letV=adj.length;// min time to reach a node from src(0)letminTime=Array(V).fill(Number.MAX_SAFE_INTEGER);// number of ways to reach a node // from src(0) with minimum costletpaths=Array(V).fill(0);minTime[0]=0;paths[0]=1;// sort nodes by time taken to reach // them from src in ascending orderletpq=[[0,0]];// [node, time]while(pq.length){pq.sort((a,b)=>a[0]-b[0]);let[currentTime,node]=pq.shift();if(currentTime>minTime[node])continue;for(let[nextNode,nextTime]ofadj[node]){letnewTime=nextTime+currentTime;// if newTime is less than stored value// then update paths and timeif(newTime<minTime[nextNode]){minTime[nextNode]=newTime;paths[nextNode]=paths[node];pq.push([newTime,nextNode]);}elseif(newTime===minTime[nextNode]){// increment the count of // paths if time is samepaths[nextNode]=(paths[nextNode]+paths[node]);}}}// return number of paths to reach // dest from src in min timereturnpaths[V-1];}//Driver Code StartsfunctionaddEdge(adj,u,v,wt){adj[u].push([v,wt]);adj[v].push([u,wt]);}// Driver codeletV=4;letadj=Array.from({length:V},()=>[]);addEdge(adj,0,1,2);addEdge(adj,0,3,5);addEdge(adj,1,2,3);addEdge(adj,1,3,3);addEdge(adj,2,3,4);console.log(countPaths(adj));//Driver Code Ends