Buggy python submission (verdict: Time Limit Exceeded):
from collections import deque


h, w = map(int, input().split())
field = [list(input()) for _ in range(h)]
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]


def check_done():
    for i in range(h):
        for j in range(w):
            if field[i][j] == ".":
                return False
    return True


def check_black_list():
    res = []
    for i in range(h):
        for j in range(w):
            if field[i][j] == "#":
                res.append((i, j))
    return res


que = deque(check_black_list())
ans = -1
done = [[False] * w for _ in range(h)]

while que:
    for i in range(len(que)):
        y, x = que.popleft()
        if y < 0 or y >= h or x < 0 or x >= w or done[y][x] is True:
            continue
        field[y][x] = "#"
        done[y][x] = True
    

        for dy, dx in directions:
            que.append((y+dy, x+dx))

    ans += 1
    if check_done():
        print(ans)
        exit()



Fixed submission:
def main():
    h,w = map(int,input().split())
    a = []
    for i in range(h):
        a.append(input())

    used = [True]*(h*w)

    p = []
    for i in range(h):
        for j in range(w):
            if a[i][j] == '#':
                p.append(i*w+j)
                used[i*w+j] = False


    
    res = 0
    while p:
        tank = []
        for e in p:
            if e>w-1 and used[e-w]:
                tank.append(e-w)
                used[e-w] = False
            if e%w > 0 and used[e-1]:
                tank.append(e-1)
                used[e-1] = False
            if e<(h-1)*w and used[e+w]:
                tank.append(e+w)
                used[e+w] = False
            if e%w<w-1 and used[e+1]:
                tank.append(e+1)
                used[e+1] =  False
        p = tank
        res += 1
    print(res-1)

if __name__ == '__main__':
    main()

Buggy python submission (verdict: Time Limit Exceeded):
from collections import deque


h, w = map(int, input().split())
field = [list(input()) for _ in range(h)]
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]


def check_done():
    for i in range(h):
        for j in range(w):
            if field[i][j] == ".":
                return False
    return True


def check_black_list():
    res = []
    for i in range(h):
        for j in range(w):
            if field[i][j] == "#":
                res.append((i, j))
    return res


que = deque(check_black_list())
ans = -1
done = [[False] * w for _ in range(h)]

while que:
    for i in range(len(que)):
        y, x = que.popleft()
        if y < 0 or y >= h or x < 0 or x >= w or done[y][x] is True:
            continue
        field[y][x] = "#"
        done[y][x] = True
    

        for dy, dx in directions:
            que.append((y+dy, x+dx))

    ans += 1
    if check_done():
        print(ans)
        exit()



Fixed submission:
def main():
    h,w = map(int,input().split())
    a = []
    for i in range(h):
        a.append(input())

    used = [True]*(h*w)

    p = []
    for i in range(h):
        for j in range(w):
            if a[i][j] == '#':
                p.append(i*w+j)
                used[i*w+j] = False


    
    res = 0
    while p:
        tank = []
        for e in p:
            if e>w-1 and used[e-w]:
                tank.append(e-w)
                used[e-w] = False
            if e%w > 0 and used[e-1]:
                tank.append(e-1)
                used[e-1] = False
            if e<(h-1)*w and used[e+w]:
                tank.append(e+w)
                used[e+w] = False
            if e%w<w-1 and used[e+1]:
                tank.append(e+1)
                used[e+1] =  False
        p = tank
        res += 1
    print(res-1)

if __name__ == '__main__':
    main()