Buggy python submission (verdict: Runtime Error):
# https://atcoder.jp/contests/aising2019/submissions/3986315
# 解説のように 連結成分を求めてから、bfsする

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

ans = 0

dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]

un_reached = [[True for i in range(W)] for j in range(H)]


def isIn(x, y):
    return 0 <= x < H and 0 <= y < W


def dfs(x, y):
    un_reached[x][y] = False
    if s[x][y] == '#':
        cc[1] += 1
    else:
        cc[0] += 1

    for i in range(4):
        nx = x+dx[i]
        ny = y+dy[i]
        if isIn(nx, ny) and s[nx][ny] != s[x][y] and un_reached[nx][ny]:
            dfs(nx, ny)


for i in range(H):
    for j in range(W):
        if un_reached[i][j]:
            cc = [0 for _ in range(2)]
            dfs(i, j)
            ans += cc[1]*cc[0]
print(ans)


Fixed submission:
# https://atcoder.jp/contests/aising2019/submissions/3986315
# 解説のように 連結成分を求めてから、bfsする
import sys
sys.setrecursionlimit(2 * 10 ** 5)

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

ans = 0

dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]

un_reached = [[True for i in range(W)] for j in range(H)]


def isIn(x, y):
    return 0 <= x < H and 0 <= y < W


def dfs(x, y):
    un_reached[x][y] = False
    if s[x][y] == '#':
        cc[1] += 1
    else:
        cc[0] += 1

    for i in range(4):
        nx = x+dx[i]
        ny = y+dy[i]
        if isIn(nx, ny) and s[nx][ny] != s[x][y] and un_reached[nx][ny]:
            dfs(nx, ny)


for i in range(H):
    for j in range(W):
        if un_reached[i][j]:
            cc = [0 for _ in range(2)]
            dfs(i, j)
            ans += cc[1]*cc[0]
print(ans)

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

mat = [['&'] * (W+2) for _ in range(H+2)]
for row in range(1, H+1):
    for col in range(1, W+1):
        mat[row][col] = grid[row-1][col-1]


def search(x, row, col, mat):
    ran = [-1, 1]
    ret = []
    for i in ran:
        if mat[row+i][col] == x:
            ret.append([row+i, col])
        if mat[row][col+i] == x:
            ret.append([row, col+i])

    return ret


def bfs(row, col, mat):
    ret = 0
    mat[row][col] = '&'

    res = search('.', row, col, mat)

    ret += len(res)
    for cand in res:
        mat[cand[0]][cand[1]] = '&'

    for cand in res:
        res2 = search('#', cand[0], cand[1], mat)
        for cand2 in res2:
            res3 = bfs(cand2[0], cand2[1], mat)
            ret += res3
    return ret


ans = 0

for row in range(1, H+1):
    for col in range(1, W+1):
        if mat[row][col] == '#':
            mat_copy = copy.deepcopy(mat)
            ans += bfs(row, col, mat_copy)

print(ans)


Fixed submission:
# https://atcoder.jp/contests/aising2019/submissions/3986315
# 解説のように 連結成分を求めてから、bfsする
import sys
sys.setrecursionlimit(2 * 10 ** 5)

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

ans = 0

dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]

un_reached = [[True for i in range(W)] for j in range(H)]


def isIn(x, y):
    return 0 <= x < H and 0 <= y < W


def dfs(x, y):
    un_reached[x][y] = False
    if s[x][y] == '#':
        cc[1] += 1
    else:
        cc[0] += 1

    for i in range(4):
        nx = x+dx[i]
        ny = y+dy[i]
        if isIn(nx, ny) and s[nx][ny] != s[x][y] and un_reached[nx][ny]:
            dfs(nx, ny)


for i in range(H):
    for j in range(W):
        if un_reached[i][j]:
            cc = [0 for _ in range(2)]
            dfs(i, j)
            ans += cc[1]*cc[0]
print(ans)