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

H, W = map(int, input().split())
S = [list(input()) for _ in range(H)]

ans = set()


def f(i, j):
    seen[i][j] = 1
    if S[i][j] == '.':
        ans.add((s, (i, j)))
    if i != 0:
        if seen[i-1][j] == 0 and S[i-1][j] != S[i][j]:
            f(i-1, j)
    if i != H-1:
        if seen[i+1][j] == 0 and S[i+1][j] != S[i][j]:
            f(i+1, j)
    if j != 0:
        if seen[i][j-1] == 0 and S[i][j-1] != S[i][j]:
            f(i, j-1)
    if j != W-1:
        if seen[i][j+1] == 0 and S[i][j+1] != S[i][j]:
            f(i, j+1)


for i in range(H):
    for j in range(W):
        if S[i][j] == '#':
            seen = [[0] * W for i in range(H)]
            s = (i, j)
            f(i, j)

print(len(ans))


Fixed submission:
import collections
import sys
sys.setrecursionlimit(1000000)


H, W = map(int, input().split())
S = [list(input()) for _ in range(H)]


seen = [[False] * W for i in range(H)]
move = ((-1, 0), (1, 0), (0, -1), (0, 1))

q = collections.deque()


def bfs(i, j):
    b, w = 0, 0
    seen[i][j] = True
    q.append((i, j))

    while q:
        ci, cj = q.popleft()

        if S[ci][cj] == '#':
            b += 1
        else:
            w += 1

        for di, dj in move:
            ni = ci+di
            nj = cj+dj
            if 0 <= ni < H and 0 <= nj < W:
                if seen[ni][nj] is False and S[ci][cj] != S[ni][nj]:
                    seen[ni][nj] = True
                    q.append((ni, nj))

    return b*w


ans = 0
for i in range(H):
    for j in range(W):
        if S[i][j] == '#' and seen[i][j] is False:
            ans += bfs(i, j)

print(ans)

Buggy python submission (verdict: Runtime Error):
H, W = map(int, input().split())
S = [list(input()) for _ in range(H)]

ans = set()


def f(i, j):
    seen[i][j] = 1
    if S[i][j] == '.':
        ans.add((s, (i, j)))
    if i != 0:
        if seen[i-1][j] == 0 and S[i-1][j] != S[i][j]:
            f(i-1, j)
    if i != H-1:
        if seen[i+1][j] == 0 and S[i+1][j] != S[i][j]:
            f(i+1, j)
    if j != 0:
        if seen[i][j-1] == 0 and S[i][j-1] != S[i][j]:
            f(i, j-1)
    if j != W-1:
        if seen[i][j+1] == 0 and S[i][j+1] != S[i][j]:
            f(i, j+1)


for i in range(H):
    for j in range(W):
        if S[i][j] == '#':
            seen = [[0] * W for i in range(H)]
            s = (i, j)
            f(i, j)

print(len(ans))


Fixed submission:
import collections
import sys
sys.setrecursionlimit(1000000)


H, W = map(int, input().split())
S = [list(input()) for _ in range(H)]


seen = [[False] * W for i in range(H)]
move = ((-1, 0), (1, 0), (0, -1), (0, 1))

q = collections.deque()


def bfs(i, j):
    b, w = 0, 0
    seen[i][j] = True
    q.append((i, j))

    while q:
        ci, cj = q.popleft()

        if S[ci][cj] == '#':
            b += 1
        else:
            w += 1

        for di, dj in move:
            ni = ci+di
            nj = cj+dj
            if 0 <= ni < H and 0 <= nj < W:
                if seen[ni][nj] is False and S[ci][cj] != S[ni][nj]:
                    seen[ni][nj] = True
                    q.append((ni, nj))

    return b*w


ans = 0
for i in range(H):
    for j in range(W):
        if S[i][j] == '#' and seen[i][j] is False:
            ans += bfs(i, j)

print(ans)