Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
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:
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:
Dijkstra's Algorithm: Starting from node n, we find the shortest distance to all other nodes
Dynamic Programming: For each node, we count paths by summing paths from neighbors that are closer to the destination
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.
