Buggy python submission (verdict: Time Limit Exceeded):
import sys
sys.setrecursionlimit(10010010)

def aising19_c():
    h, w = (int(x) for x in input().split())
    grid = [[s for s in str(input())] for _ in range(h)]
    visited = [[False]*w for _ in range(h)]
    ans = 0

    def dfs(x, y):
        nonlocal ans
        visited[x][y] = True
        for dx, dy in ((-1,0),(0,-1),(0,1),(1,0)):
            nx, ny = x+dx, y+dy
            if nx < 0 or h <= nx or ny < 0 or w <= ny: continue
            if grid[nx][ny] == grid[x][y]: continue
            if visited[nx][ny]: continue
            if grid[nx][ny] == '.': ans += 1
            dfs(nx, ny)

    for i in range(h):
        for j in range(w):
            if grid[i][j] == '#':
                dfs(i, j)
                visited = [[False]*w for _ in range(h)]
    print(ans)

if __name__ == '__main__':
    aising19_c()

Fixed submission:
def aising19_c():
    from collections import deque

    h, w = (int(x) for x in input().split())
    color = [[s == '#' for s in str(input())] for _ in range(h)]
    used = [[False]*w for _ in range(h)]

    ans = 0
    for i in range(h):
        for j in range(w):
            if used[i][j]: continue
            bk, wt = 0, 0
            que = deque()
            used[i][j] = True
            que.append((i, j))
            while que:
                ci, cj = que.popleft()
                if color[ci][cj]: bk += 1
                else: wt += 1
                for di, dj in ((-1,0),(0,-1),(0,1),(1,0)):
                    ni, nj = ci+di, cj+dj
                    if ni < 0 or h <= ni or nj < 0 or w <= nj: continue
                    if color[ci][cj] == color[ni][nj]: continue
                    if used[ni][nj]: continue
                    used[ni][nj] = True
                    que.append((ni, nj))
            ans += bk * wt
    print(ans)

if __name__ == '__main__':
    aising19_c()

Buggy python submission (verdict: Runtime Error):
def aising19_c():
    h, w = (int(x) for x in input().split())
    grid = [[s for s in str(input())] for _ in range(h)]
    visited = [[False]*w for _ in range(h)]
    ans = 0

    def dfs(x, y):
        nonlocal ans
        visited[x][y] = True
        for dx, dy in ((-1,0),(0,-1),(0,1),(1,0)):
            nx, ny = x+dx, y+dy
            if nx < 0 or h <= nx or ny < 0 or w <= ny: continue
            if grid[nx][ny] == grid[x][y]: continue
            if visited[nx][ny]: continue
            if grid[nx][ny] == '.': ans += 1
            dfs(nx, ny)

    for i in range(h):
        for j in range(w):
            if grid[i][j] == '#':
                dfs(i, j)
                visited = [[False]*w for _ in range(h)]
    print(ans)

if __name__ == '__main__':
    aising19_c()

Fixed submission:
def aising19_c():
    from collections import deque

    h, w = (int(x) for x in input().split())
    color = [[s == '#' for s in str(input())] for _ in range(h)]
    used = [[False]*w for _ in range(h)]

    ans = 0
    for i in range(h):
        for j in range(w):
            if used[i][j]: continue
            bk, wt = 0, 0
            que = deque()
            used[i][j] = True
            que.append((i, j))
            while que:
                ci, cj = que.popleft()
                if color[ci][cj]: bk += 1
                else: wt += 1
                for di, dj in ((-1,0),(0,-1),(0,1),(1,0)):
                    ni, nj = ci+di, cj+dj
                    if ni < 0 or h <= ni or nj < 0 or w <= nj: continue
                    if color[ci][cj] == color[ni][nj]: continue
                    if used[ni][nj]: continue
                    used[ni][nj] = True
                    que.append((ni, nj))
            ans += bk * wt
    print(ans)

if __name__ == '__main__':
    aising19_c()