Program to find number of restricted paths from first to last node in Python

Suppose we have an undirected weighted connected graph with n nodes labeled from 1 to n. A restricted path is a special path from node 1 to node n where the distance to the destination decreases at each step. Specifically, for a path [z0, z1, z2, ..., zk], we need dist(zi) > dist(zi+1) where dist(x) is the shortest distance from node x to node n.

We need to find the number of restricted paths from node 1 to node n, returning the result modulo 10^9 + 7.

For example, if we have this graph:

1 2 3 4 5 3 3 1 2 1 10 2

The restricted paths are: (1,2,5), (1,2,3,5), and (1,3,5), giving us 3 total paths.

Algorithm

We use Dijkstra's algorithm with dynamic programming to solve this problem ?

  • Build an adjacency list representation of the graph

  • Use Dijkstra's algorithm starting from node n to find shortest distances to all nodes

  • Count paths using dynamic programming: when processing a node, add paths from neighbors with smaller distances

  • Return the number of paths to node 1 modulo 10^9 + 7

Implementation

from collections import defaultdict
from heapq import heappop, heappush

def solve(n, edges):
    # Build adjacency list
    graph = defaultdict(dict)
    for u, v, w in edges:
        graph[u][v] = w
        graph[v][u] = w

    # Initialize paths and distances
    paths = [0] * (n + 1)
    paths[n] = 1  # Base case: 1 way to reach destination from itself
    dists = [-1] * (n + 1)
    
    # Priority queue for Dijkstra's algorithm
    pq = [(0, n)]  # (distance, node)

    while pq:
        dist, node = heappop(pq)
        
        # Skip if already processed
        if dists[node] != -1:
            continue

        dists[node] = dist
        
        # Process all neighbors
        for neighbor, weight in graph[node].items():
            if dists[neighbor] == -1:
                # Add to queue for processing
                heappush(pq, (dist + weight, neighbor))
            elif dists[neighbor] < dists[node]:
                # Valid restricted path: add paths from this neighbor
                paths[node] = (paths[node] + paths[neighbor]) % (10**9 + 7)

        # Return result when we reach node 1
        if node == 1:
            return paths[node]

    return 0

# Test the solution
n = 5
edges = [(1,2,3), (1,3,3), (2,3,1), (1,4,2), (5,2,2), (3,5,1), (5,4,10)]
result = solve(n, edges)
print(f"Number of restricted paths: {result}")
Number of restricted paths: 3

How It Works

The algorithm combines Dijkstra's shortest path algorithm with dynamic programming:

  1. Dijkstra's Algorithm: Starting from node n, we find the shortest distance to all other nodes

  2. Dynamic Programming: For each node, we count paths by summing paths from neighbors that are closer to the destination

  3. Restricted Path Condition: We only add paths from neighbors where dists[neighbor] < dists[node]

Time Complexity

The time complexity is O(E log V) where E is the number of edges and V is the number of vertices, due to Dijkstra's algorithm using a priority queue.

Conclusion

This solution efficiently finds restricted paths by combining Dijkstra's algorithm with dynamic programming. The key insight is processing nodes in order of increasing distance from the destination, ensuring all shorter paths are counted before longer ones.

Updated on: 2026-03-26T14:16:56+05:30

324 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements