githubEdit

18. Number of Ways to Arrive at Destination

βœ… GFG solution to Number of Ways to Arrive at Destination: count all shortest paths from source to destination using Dijkstra's algorithm with path counting. πŸš€

The problem can be found at the following link: πŸ”— Question Linkarrow-up-right

🧩 Problem Description

You are given an undirected weighted graph with V vertices numbered from 0 to V-1 and E edges, represented as a 2D array edges[][], where edges[i] = [ui, vi, timei] means that there is an undirected edge between nodes ui and vi that takes timei minutes to reach.

Your task is to return in how many ways you can travel from node 0 to node V - 1 in the shortest amount of time.

πŸ“˜ Examples

Example 1

Input: V = 4, edges[][] = [[0, 1, 2], [1, 2, 3], [0, 3, 5], [1, 3, 3], [2, 3, 4]]
Output: 2
Explanation: The shortest path from 0 to 3 is 5.
Two ways to reach 3 in 5 minutes are:
0 -> 3
0 -> 1 -> 3

Example 2

Input: V = 6, edges[][] = [[0, 2, 3], [0, 4, 2], [0, 5, 7], [2, 3, 1], [2, 5, 5], [5, 3, 3], [5, 1, 4], [1, 4, 1], [4, 5, 5]]
Output: 4
Explanation: The shortest path from 0 to 5 is 7.
Four ways to reach 5 in 7 minutes are:
0 -> 5
0 -> 4 -> 5
0 -> 4 -> 1 -> 5
0 -> 2 -> 3 -> 5

πŸ”’ Constraints

  • $1 \le V \le 200$

  • $V - 1 \le \text{edges.size()} \le V \times (V - 1) / 2$

  • $0 \le u_i, v_i \le V - 1$

  • $1 \le \text{time}_i \le 10^5$

  • $u_i \ne v_i$

βœ… My Approach

The optimal solution uses Dijkstra's Algorithm combined with path counting to efficiently compute both shortest distances and the number of ways to reach each node:

Dijkstra's Algorithm with Path Counting

  1. Initialize Data Structures:

    • Create adjacency list to represent the graph with edge weights.

    • Maintain dist[] array initialized to infinity (except source = 0).

    • Maintain ways[] array to count paths (source has 1 way).

    • Use min-heap priority queue sorted by distance.

  2. Process Nodes in Distance Order:

    • Extract node with minimum distance from priority queue.

    • Skip if current distance is outdated (already processed with shorter path).

  3. Relax Adjacent Edges:

    • For each neighbor, calculate new distance through current node.

    • If new distance is shorter: update distance, copy path count, add to queue.

    • If new distance equals current shortest: add current node's paths to neighbor's count.

  4. Apply Modulo:

    • Since path counts can be large, apply modulo $10^9 + 7$ to prevent overflow.

  5. Return Result:

    • Return the count of shortest paths to destination node (V-1).

πŸ“ Time and Auxiliary Space Complexity

  • Expected Time Complexity: O((V + E) log V), as we process each vertex once and each edge may be relaxed multiple times. The priority queue operations (insertion and extraction) take O(log V) time, and we perform these operations for all edges in the worst case.

  • Expected Auxiliary Space Complexity: O(V + E), where O(V) is used for the distance and ways arrays, and O(E) is used for storing the adjacency list representation of the graph. The priority queue also uses O(V) space in the worst case.

πŸ§‘β€πŸ’» Code (C++)

chevron-right⚑ View Alternative Approaches with Code and Analysishashtag

πŸ“Š 2️⃣ BFS-Based Level Processing

πŸ’‘ Algorithm Steps:

  1. Use BFS to process nodes level by level based on distance.

  2. Maintain a queue sorted by distance using map structure.

  3. Update paths when finding equal or shorter distances.

  4. Process all nodes at same distance level together.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(E log V) - Map operations for level processing

  • Auxiliary Space: πŸ’Ύ O(V + E) - Level map and adjacency list

βœ… Why This Approach?

  • Level-by-level distance processing

  • Natural BFS structure for path problems

  • Useful when distance-based grouping is needed

πŸ“Š 3️⃣ DFS with Memoization

πŸ’‘ Algorithm Steps:

  1. Recursively explore all paths from source to destination.

  2. Memoize computed distances and path counts for each node.

  3. Combine results from all valid paths with minimum distance.

  4. Return accumulated count for destination with shortest distance.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(V + E) - Visit each node and edge once with memoization

  • Auxiliary Space: πŸ’Ύ O(V) - Recursion stack and memoization arrays

βœ… Why This Approach?

  • Recursive solution pattern

  • Natural for tree-like structures

  • Intuitive path exploration logic

Note: This approach results in Time Limit Exceeded (TLE) for large inputs (fails ~1110/1120 test cases due to time constraints).

πŸ†š πŸ” Comparison of Approaches

πŸš€ Approach

⏱️ Time Complexity

πŸ’Ύ Space Complexity

βœ… Pros

⚠️ Cons

🏷️ Dijkstra Priority Queue

🟒 O((V+E) log V)

🟒 O(V+E)

πŸš€ Optimal for sparse graphs

πŸ”§ Requires priority queue

πŸ“Š BFS Levels

🟑 O(E log V)

🟑 O(V + E)

🎯 Natural level processing

πŸ’Ύ Map overhead

πŸ”„ DFS Memoization

🟒 O(V+E)

🟑 O(V)

⭐ Recursive pattern

πŸ”§ Stack overflow risk

πŸ† Best Choice Recommendation

🎯 Scenario

πŸŽ–οΈ Recommended Approach

πŸ”₯ Performance Rating

πŸ… Sparse graphs optimal

πŸ₯‡ Dijkstra Priority Queue

β˜…β˜…β˜…β˜…β˜…

πŸ”§ Distance grouping needed

πŸ₯ˆ BFS Levels

β˜…β˜…β˜…β˜…β˜†

🎯 Recursive preference

πŸ… DFS Memoization

β˜…β˜…β˜…β˜…β˜†

β˜• Code (Java)

🐍 Code (Python)

🧠 Contribution and Support

For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: πŸ“¬ Any Questions?arrow-up-right. Let's make this learning journey more collaborative!

⭐ If you find this helpful, please give this repository a star! ⭐


πŸ“Visitor Count

Visitor counter

Last updated