AlgoMaster Logo

Number of Ways to Arrive at Destination

mediumFrequency6 min readUpdated June 23, 2026

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 an 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. We 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.

Whenever Dijkstra relaxes an edge and finds a new shortest distance to some node, the count of shortest paths to that node equals the count of the node we came from. 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, small enough that even an O(n^3) approach would finish in time.
  • 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 → A path can have up to 199 edges, so the total distance can reach roughly 2 x 10^11, which overflows a 32-bit int. Distances must use 64-bit integers.
  • modulo 10^9 + 7 → The path count can grow large, so we take it modulo a prime.

Approach 1: DFS Enumerate All Paths (Brute Force)

Intuition

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

We enumerate paths using DFS. Starting from node 0, we explore every 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

Enumerating every path is exponentially slow, and shared subpaths get recomputed across routes. The next approach computes the shortest distance to each node once and accumulates the path counts during a single graph traversal.

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

Intuition

Dijkstra's algorithm processes nodes in order of their shortest distance from the source. When we pop a node from the priority queue, its final shortest distance is fixed. We can attach a counting mechanism on top of that.

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, since there is one path from the start to itself, the empty path.

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:
    • Pop the node with the smallest distance. Call it (d, u).
    • If d > dist[u], skip (stale entry).
    • 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).
  5. Return ways[n-1].

Example Walkthrough

dist
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
ways
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