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

1 2 3 4 10 5 20 15

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:

  1. Pop the minimum cost node from the heap
  2. Mark it as visited to avoid cycles
  3. If it's the destination, return the cost
  4. For each neighbor, calculate new penalty using bitwise OR
  5. 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.

Updated on: 2026-03-26T14:21:57+05:30

400 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements