-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGeeksforgeeks_Shortest Path Using Atmost One Curved Edge.py
More file actions
71 lines (52 loc) · 2.96 KB
/
Geeksforgeeks_Shortest Path Using Atmost One Curved Edge.py
File metadata and controls
71 lines (52 loc) · 2.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# Given an undirected, connected graph with V vertices numbered from 0 to V-1 and E double-edges, represented as a 2D array edges[][]. Each double-edge is represented by a tuple (x, y, w1, w2), which indicates that there are two edges between vertices x and y: a straight edge with weight w1 and a curved edge with weight w2.
# You are given two vertices a and b and you have to go from a to b through a series of edges such that in the entire path, you can use at most 1 curved edge. Your task is to find the shortest path from a to b satisfying the above condition.
# If no such path exists that satisfies this restriction, return -1.
# Note: It is guaranteed that the shortest path value will fit in a 32-bit integer.
# Examples:
# Input: V = 4, E = 4, a = 1, b = 3, edges[][] = [[0, 1, 1, 4], [0, 2, 2, 4], [0, 3, 3, 1], [1, 3, 6, 5]]
# Output: 2
# Explanation:
# We can follow the path 1 -> 0 -> 3, this gives a distance of 1+3 = 4 if we follow all straight paths. But we can take the curved path from 0 -> 3, which costs 1. This will result in a cost of 1 + 1 = 2.
# Input: V = 2, E = 1, a = 0, b = 1, edges[][] = [[0, 1, 4, 1]]
# Output: 1
# Explanation:
# Take the curved path from 0 to 1 which costs 1.
# Constraints:
# 1 ≤ V ≤ 106
# 0 ≤ E ≤ 106
# 0 ≤ a, b ≤ V - 1
# 0 ≤ edges[i][0], edges[i][1] ≤ V-1
# 0 ≤ edges[i][2], edges[i][3] ≤ 104
class Solution:
def shortestPath(self, V, a, b, edges):
INF = 10**9
# Build adjacency list: each edge has straight weight w1 and curved weight w2
adj = [[] for _ in range(V)]
for u, v, w1, w2 in edges:
adj[u].append((v, w1, w2))
adj[v].append((u, w1, w2)) # undirected graph assumption
# dist[node][usedCurveFlag]
dist = [[INF, INF] for _ in range(V)]
# PQ stores state in the form of (distance, node, usedCurve)
pq = []
# Start from 'a' without using any curved edge
dist[a][0] = 0
heapq.heappush(pq, (0, a, 0))
while pq:
d, node, used = heapq.heappop(pq)
if d != dist[node][used]:
continue
# Explore all neighbors of 'node'
for nxt, w1, w2 in adj[node]:
# Take straight edge - usedCurve remains same
if dist[nxt][used] > d + w1:
dist[nxt][used] = d + w1
heapq.heappush(pq, (dist[nxt][used], nxt, used))
# Use curved edge (only if not used before)
if used == 0:
if dist[nxt][1] > d + w2:
dist[nxt][1] = d + w2
heapq.heappush(pq, (dist[nxt][1], nxt, 1))
# Minimum of both possibilities (curved edge used or not)
ans = min(dist[b][0], dist[b][1])
return -1 if ans >= INF else ans