Program to count number of walls required to partition top-left and bottom-right cells in Python

In this problem, we need to find the minimum number of walls required to block all paths between the top-left cell (0,0) and bottom-right cell (R-1,C-1) in a 2D binary matrix. The matrix contains 0s (empty cells) and 1s (existing walls), and we can only move in four directions (up, down, left, right).

Problem Understanding

Given a matrix where 0 represents empty cells and 1 represents walls, we need to determine the minimum number of additional walls to place so that there's no path from top-left to bottom-right. We cannot place walls on the start and end positions.

Example

For the input matrix:

0 0 0 0
0 1 0 0
0 1 1 0
0 0 0 0

The output is 2, meaning we need to add 2 walls to block all paths:

0 1 0 0
0 1 0 0
0 1 1 0
0 0 1 0

Algorithm Approach

This problem uses Tarjan's algorithm to find articulation points (bridge points) in the graph. The key insight is:

  • If no path exists initially, return 0
  • If removing any single articulation point disconnects the graph, return 1
  • Otherwise, we need 2 walls to block all paths, return 2

Implementation

from collections import deque

class Solution:
    def solve(self, matrix):
        R = len(matrix)
        C = len(matrix[0])
        
        def get_neighbors(i, j):
            for ii, jj in ((i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)):
                if 0 <= ii < R and 0 <= jj < C and matrix[ii][jj] == 0:
                    yield ii, jj
        
        visited = set()
        tin = {}
        low = {}
        timer = 0
        bridge_pts = set()
        par = {}
        src = (0, 0)
        tgt = (R - 1, C - 1)
        
        def dfs(v, parent):
            nonlocal timer
            visited.add(v)
            par[v] = parent
            tin[v] = timer
            low[v] = timer
            timer += 1
            children = 0
            
            for to in get_neighbors(*v):
                if to == parent:
                    continue
                if to in visited:
                    low[v] = min(low[v], tin[to])
                else:
                    dfs(to, v)
                    low[v] = min(low[v], low[to])
                    if low[to] >= tin[v] and parent is not None:
                        bridge_pts.add(v)
                    children += 1
            
            if parent is None and children > 1:
                bridge_pts.add(v)
        
        def bfs(root):
            Q = deque([root])
            visited_bfs = set([root])
            while Q:
                v = Q.pop()
                if v == tgt:
                    return True
                for w in get_neighbors(*v):
                    if w not in visited_bfs:
                        visited_bfs.add(w)
                        Q.appendleft(w)
            return False
        
        # Main algorithm
        dfs(src, None)
        
        # If target not reachable, no walls needed
        if tgt not in par:
            return 0
        
        # Mark articulation points as walls
        for i, j in bridge_pts:
            matrix[i][j] = 1
        
        # Check if path still exists after blocking articulation points
        if bfs(src):
            return 2
        return 1

# Test the solution
ob = Solution()
matrix = [
    [0, 0, 0, 0],
    [0, 1, 0, 0],
    [0, 1, 1, 0],
    [0, 0, 0, 0],
]
print(ob.solve(matrix))

Output

2

How It Works

The algorithm works in three phases:

  1. DFS with Tarjan's Algorithm: Find all articulation points in the graph formed by empty cells
  2. Check Connectivity: If target is unreachable initially, return 0
  3. Test Blocking: Temporarily block articulation points and check if path still exists using BFS

Time Complexity

The time complexity is O(R × C) where R and C are the matrix dimensions, as we visit each cell at most twice during DFS and BFS traversals.

Conclusion

This solution efficiently finds the minimum walls needed by identifying critical nodes (articulation points) whose removal would disconnect the graph. The answer is always 0, 1, or 2 depending on the graph structure and connectivity.

---
Updated on: 2026-03-25T13:59:03+05:30

305 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements