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 out the path between two vertices in a graph that has the minimum penalty (Python)
When working with weighted graphs, sometimes we need to find a path that minimizes a specific cost function. In this problem, we find the path between two vertices where the penalty is minimized. The penalty of a path is the bitwise OR of all edge weights in the path.
Given an undirected, weighted graph, we need to find the minimum penalty path from node a to node b. If no path exists, we return -1.
Problem Example
For start = 1, end = 3: There are two possible paths ?
- Path 1?4?3: penalty = (20 OR 15) = 31
- Path 1?2?3: penalty = (10 OR 5) = 15
The optimal path is 1?2?3 with minimum penalty of 15.
Algorithm Approach
We use a modified Dijkstra's algorithm where instead of adding weights, we use bitwise OR operation. The key insight is that bitwise OR is monotonic ? once a bit is set, it cannot be unset.
Implementation
import heapq
from math import inf
def helper(graph, start, end):
visited = set()
costs = [inf] * len(graph)
heap = [(0, start)]
while heap:
current_cost, current_node = heapq.heappop(heap)
costs[current_node] = min(current_cost, costs[current_node])
if (current_cost, current_node) in visited:
continue
if current_node == end:
return costs[current_node]
visited.add((current_cost, current_node))
for neighbor, edge_weight in graph[current_node]:
new_cost = edge_weight | current_cost
heapq.heappush(heap, (new_cost, neighbor))
return costs[end]
def find_min_penalty_path(n, edges, start, end):
# Build adjacency list
graph = [[] for _ in range(n + 1)]
for u, v, weight in edges:
graph[u].append((v, weight))
graph[v].append((u, weight))
result = helper(graph, start, end)
return -1 if result == inf else result
# Test with the example
n = 4
edges = [(1, 2, 10), (2, 3, 5), (2, 4, 15), (1, 4, 20)]
start, end = 1, 3
print(f"Minimum penalty path from {start} to {end}: {find_min_penalty_path(n, edges, start, end)}")
Minimum penalty path from 1 to 3: 15
How It Works
The algorithm maintains a priority queue with (cost, node) pairs, where cost represents the cumulative bitwise OR penalty. For each node, we:
- Pop the minimum cost node from the heap
- Mark it as visited to avoid cycles
- If it's the destination, return the cost
- For each neighbor, calculate new penalty using bitwise OR
- Push the neighbor to the heap for further exploration
Key Points
- Bitwise OR property: OR operation is monotonic ? penalty can only increase or stay the same
- Modified Dijkstra: Uses OR instead of addition for path costs
- Priority queue: Ensures we always explore the minimum penalty path first
- Visited tracking: Prevents infinite loops in the graph
Conclusion
This algorithm efficiently finds the minimum penalty path using a modified Dijkstra's approach with bitwise OR. The time complexity is O(E log V) where E is edges and V is vertices, making it suitable for medium-sized graphs.
