AlgoMaster Logo

Number of Ways to Arrive at Destination

Last Updated: April 2, 2026

medium
4 min read

Understanding the Problem

We have a weighted undirected graph and need to find two things: the shortest path distance from node 0 to node n-1, and the number of distinct shortest paths that achieve that distance.

This is a classic extension of Dijkstra's algorithm. Standard Dijkstra finds the shortest distance, but here we also need to count how many different paths produce that same shortest distance. The trick is to maintain a count array alongside the distance array. When we find a shorter path to a node, we reset its count. When we find another path with the same shortest distance, we add to the count.

The key observation: whenever Dijkstra relaxes an edge and finds a new shortest distance to some node, we know the count of shortest paths to that node is exactly the count of the node we came from. And if we find an equally short path through a different node, we add that node's count to the running total.

Key Constraints:

  • 1 <= n <= 200 → The graph has at most 200 nodes. This is small enough for O(n^2) or O(n^2 log n) approaches. Even Floyd-Warshall at O(n^3) would be 8 million operations, perfectly fine.
  • n - 1 <= roads.length <= n * (n - 1) / 2 → The graph is connected (at least n-1 edges) and can be dense (up to ~20,000 edges for n=200).
  • 1 <= time_i <= 10^9 → Edge weights can be very large, so the total shortest path distance can exceed the int range. We need long/64-bit integers for distance tracking.
  • modulo 10^9 + 7 → The number of paths can be astronomically large, so we take the count modulo a prime.

Approach 1: DFS Enumerate All Paths (Brute Force)

Intuition

The most direct approach: find all possible paths from node 0 to node n-1, compute each path's total weight, find the minimum weight among all paths, and count how many paths have that minimum weight.

We can enumerate paths using DFS. Starting from node 0, we explore every possible route to node n-1, tracking the accumulated distance. After exploring all paths, we know the shortest distance and can count how many paths match it.

This is correct but wildly inefficient. The number of simple paths in a graph can be exponential (factorial in the worst case for dense graphs). With n up to 200, this is completely impractical.

Algorithm

  1. Build an adjacency list from the roads array.
  2. Run DFS from node 0, tracking visited nodes to avoid cycles and accumulating path weight.
  3. When reaching node n-1, record the total weight.
  4. After exploring all paths, find the minimum weight and count paths with that weight.
  5. Return the count modulo 10^9 + 7.

Example Walkthrough

1Start DFS from node 0. Exploring all paths to node 6.
1/6

Code

We are enumerating every possible path, which is exponentially slow. Many subpaths are shared between routes but get recomputed. What if we computed the shortest distance to each node just once and counted the shortest paths incrementally?

Approach 2: Dijkstra's Algorithm with Path Counting (Optimal)

Intuition

Here is the core insight: Dijkstra's algorithm already processes nodes in order of their shortest distance from the source. When we pop a node from the priority queue, we know its final shortest distance. So we can piggyback a counting mechanism on top of Dijkstra.

We maintain two arrays: dist[i] for the shortest distance from node 0 to node i, and ways[i] for the number of shortest paths from node 0 to node i. Initially, dist[0] = 0 and ways[0] = 1 (there is exactly one way to be at the start: you are already there).

When we relax an edge from node u to node v with weight w, three things can happen:

  • Found a shorter path: dist[u] + w < dist[v]. We update dist[v] and set ways[v] = ways[u], because all previous paths to v are no longer shortest, and the only shortest paths to v now come through u.
  • Found an equally short path: dist[u] + w == dist[v]. We add ways[u] to ways[v], because we discovered additional shortest paths that go through u.
  • Found a longer path: dist[u] + w > dist[v]. We ignore it completely.

Algorithm

  1. Build an adjacency list from the roads array.
  2. Initialize dist array with infinity and ways array with 0. Set dist[0] = 0 and ways[0] = 1.
  3. Push (0, 0) (distance, node) into a min-heap.
  4. While the heap is not empty:

a. Pop the node with the smallest distance. Call it (d, u).

b. If d > dist[u], skip (stale entry).

c. For each neighbor v with edge weight w:

  • If dist[u] + w < dist[v]: update dist[v] = dist[u] + w, set ways[v] = ways[u], push to heap.
  • If dist[u] + w == dist[v]: add ways[u] to ways[v] (modulo 10^9+7).
  1. Return ways[n-1].

Example Walkthrough

1Initialize: dist[0]=0, all others INF. Push (0, node 0) to heap.
0
0
start
1
INF
2
INF
3
INF
4
INF
5
INF
6
INF
1/8
1Initialize: ways[0]=1 (one way to be at the start)
0
1
start
1
0
2
0
3
0
4
0
5
0
6
0
1/8

Code