Number of Ways to Arrive at Destination — Medium Problem & Solution
A city has n intersections numbered 0 … n - 1 joined by bidirectional roads; roads[i] = [u, v, time] gives the time to drive that road.
- Difficulty: Medium
- Topics: Dynamic Programming, Graph, Topological Sort, Shortest Path
- Asked at: Amazon, Google, Microsoft
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
A city has n intersections numbered 0 … n - 1 joined by bidirectional roads; roads[i] = [u, v, time] gives the time to drive that road.
You start at intersection 0 and want to reach intersection n - 1 in the shortest possible time. Return how many different routes achieve that time, modulo 10^9 + 7.
Example 1
Input: n = 7, roads = [[0,6,7],[0,1,2],[1,2,3],[1,3,3],[6,3,3],[3,5,1],[6,5,1],[2,5,1],[0,4,5],[4,6,2]]
Output: 4
Explanation: Four different routes all take 7 minutes.
Example 2
Input: n = 2, roads = [[1,0,10]]
Output: 1
Explanation: Only one road.
Example 3
Input: n = 3, roads = [[0,1,1],[1,2,1],[0,2,2]]
Output: 2
Explanation: Two routes both take 2 minutes.
Constraints
1 <= n <= 200n - 1 <= roads.length <= n * (n - 1) / 2roads[i].length == 30 <= u, v <= n - 11 <= time <= 1000u != vThere is at most one road connecting any two intersections.You can reach any intersection from any other intersection.
How to solve Number of Ways to Arrive at Destination
Dijkstra's algorithm with path counting. Alongside dist[v], keep ways[v]: when relaxing an edge, a strictly better distance replaces the count, and an equal distance adds to it.
Approach
- Set
dist[0] = 0andways[0] = 1; everything else is infinity with 0 ways. - Repeatedly finalise the unfinished node with the smallest distance.
- Relaxing
u → v: ifdist[u] + t < dist[v], setdist[v]andways[v] = ways[u]; if equal, addways[u]intoways[v]modulo10^9 + 7. - Return
ways[n - 1].
Why it works
Counting works because a node's distance is final when it is popped: since every road takes positive time, no later discovery can shorten it, so every contribution it makes afterwards is genuinely on a shortest route. Only ways needs the modulus — dist is a real time and must stay exact, or comparisons between routes would go wrong.
Complexity
- Time —
O(n² + m) with a plain Dijkstra - Space —
O(n + m)
Pitfalls
- Reducing
distunder the modulus destroys the comparisons; onlywaysis reduced. - Equal-distance routes must add counts, not overwrite them.
- Roads are bidirectional, so each one goes into both adjacency lists.
Reference solution
Python
from typing import List
import heapq
def countPaths(n: int, roads: List[List[int]]) -> int:
MOD = 1000000007
adj = [[] for _ in range(n)]
for u, v, t in roads:
adj[u].append((v, t))
adj[v].append((u, t))
BIG = float('inf')
dist = [BIG] * n
ways = [0] * n
dist[0] = 0
ways[0] = 1
heap = [(0, 0)]
done = [False] * n
while heap:
d, u = heapq.heappop(heap)
if done[u]:
continue
done[u] = True
for v, t in adj[u]:
if done[v]:
continue
nd = d + t
if nd < dist[v]:
dist[v] = nd
ways[v] = ways[u]
heapq.heappush(heap, (nd, v))
elif nd == dist[v]:
ways[v] = (ways[v] + ways[u]) % MOD
return ways[n - 1]JavaScript
var countPaths = function(n, roads) {
var MOD = 1000000007, BIG = 1000000000, i, k;
var adj = [];
for (i = 0; i < n; i++) adj.push([]);
for (i = 0; i < roads.length; i++) {
adj[roads[i][0]].push([roads[i][1], roads[i][2]]);
adj[roads[i][1]].push([roads[i][0], roads[i][2]]);
}
var dist = [], ways = [], done = [];
for (i = 0; i < n; i++) { dist.push(BIG); ways.push(0); done.push(false); }
dist[0] = 0;
ways[0] = 1;
for (var it = 0; it < n; it++) {
var u = -1, best = BIG;
for (i = 0; i < n; i++) {
if (!done[i] && dist[i] < best) { best = dist[i]; u = i; }
}
if (u < 0) break;
done[u] = true;
for (k = 0; k < adj[u].length; k++) {
var v = adj[u][k][0], t = adj[u][k][1];
if (done[v]) continue;
var nd = dist[u] + t;
if (nd < dist[v]) {
dist[v] = nd;
ways[v] = ways[u];
} else if (nd === dist[v]) {
ways[v] = (ways[v] + ways[u]) % MOD;
}
}
}
return ways[n - 1];
};Also on the editorial tab: C, C#, C++, Go, Java, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.