Buggy python submission (verdict: Runtime Error):
import numpy as np
h, w = map(int, input().split())
colors = np.zeros((h,w))
for i in range(h):
    s = input()
    for j,c in enumerate(s):
        if c=='#':
            colors[i,j] = 1

def tonari(pos):
    i,j = pos
    ans = []
    if i==0:
        ans.append((i+1,j))
    elif i==h-1:
        ans.append((i-1,j))
    else:
        ans.append((i-1,j))
        ans.append((i+1,j))
    if j==0:
        ans.append((i,j+1))
    elif j==w-1:
        ans.append((i,j-1))
    else:
        ans.append((i,j-1))
        ans.append((i,j+1))
    
    return ans

# 深さ優先探索をする
# マス(0,0)からスタート
# 次の仕切り直しで使うスタート位置のリストnext_start
# すでに訪ねたかどうかを表すh*wの表 visited=1 
# current_positionの前後左右を見てもしcurrent_colorと異なればそっちに動く

current_position = (0,0)
current_color = colors[current_position]
current_group = 0
groups = {0:[1-current_color, current_color]} # {group_num:(white_num,black_num)}
next_visit = []
other_group = []

unvisited = [(i,j) for i in range(h) for j in range(w)]
unvisited.remove((0,0))

while True:
    # current_positionの前後左右を見る
    #print(current_position, groups)
    neighbors = tonari(current_position)
    for ngb in neighbors:
        if colors[ngb] != current_color and ngb in unvisited and ngb not in next_visit:
            next_visit.append(ngb)
        # もしnon_visitedかつcurrent_colorと異なればnext_visitに追加
        # それ以外は何もしない
    
    #print(next_visit)

    # next_visitが空でないとき
    if len(next_visit) > 0:
        current_position = next_visit.pop()
        current_color = colors[current_position]
        groups[current_group][int(current_color)] += 1
        unvisited.remove(current_position)
        # next_visitの中から次の移動先を取り出して
        # colorをみてgroupに追加
        # current_positionとcurrent_colorを更新

    elif len(next_visit) == 0:
        # next_visitが空のとき
        if len(unvisited) == 0:
            break
        else:
            current_position = unvisited.pop()
            current_color = colors[current_position]
            current_group += 1
            groups[current_group] = [1-current_color, current_color]
            # unvisitedの中から一つ選んで
            # current_position, color更新
            # current_group更新

#print(groups)
ans = 0
for g in groups:
    black, white = groups[g]
    ans += black*white
print(int(ans))



Fixed submission:
import sys
sys.setrecursionlimit(1000000)

h,w=map(int,input().split())
s=[input() for _ in range(h)]
t=[[None]*w for _ in range(h)]

def dfs(i,j,color):

  if not (0<=i<h and 0<=j<w):return 0,0
  if s[i][j]==color: return 0,0
  if t[i][j]:return 0,0

  t[i][j]=True
  wh,bl=0,0
  if s[i][j]=="#":
    bl+=1
  else:
    wh+=1

  tmp1,tmp2=dfs(i+1,j,s[i][j])
  wh,bl=wh+tmp1,bl+tmp2

  tmp1,tmp2=dfs(i-1,j,s[i][j])
  wh,bl=wh+tmp1,bl+tmp2
        
  tmp1,tmp2=dfs(i,j-1,s[i][j])
  wh,bl=wh+tmp1,bl+tmp2

  tmp1,tmp2=dfs(i,j+1,s[i][j])
  wh,bl=wh+tmp1,bl+tmp2

  return wh,bl

ans=0
for i in range(h):
  for j in range(w):
    a,b=dfs(i,j,"!")
    ans+=a*b

print(ans)

Buggy python submission (verdict: Runtime Error):
import numpy as np
h, w = map(int, input().split())
colors = np.zeros((h,w))
for i in range(h):
    s = input()
    for j,c in enumerate(s):
        if c=='#':
            colors[i,j] = 1

def tonari(pos):
    i,j = pos
    ans = []
    if i==0:
        ans.append((i+1,j))
    elif i==h-1:
        ans.append((i-1,j))
    else:
        ans.append((i-1,j))
        ans.append((i+1,j))
    if j==0:
        ans.append((i,j+1))
    elif j==w-1:
        ans.append((i,j-1))
    else:
        ans.append((i,j-1))
        ans.append((i,j+1))
    
    return ans

# 深さ優先探索をする
# マス(0,0)からスタート
# 次の仕切り直しで使うスタート位置のリストnext_start
# すでに訪ねたかどうかを表すh*wの表 visited=1 
# current_positionの前後左右を見てもしcurrent_colorと異なればそっちに動く

current_position = (0,0)
current_color = colors[current_position]
current_group = 0
groups = {0:[1-current_color, current_color]} # {group_num:(white_num,black_num)}
next_visit = []
other_group = []

unvisited = [(i,j) for i in range(h) for j in range(w)]
unvisited.remove((0,0))

while True:
    # current_positionの前後左右を見る
    # print(current_position)
    neighbors = tonari(current_position)
    for ngb in neighbors:
        if colors[ngb] != current_color and ngb in unvisited and ngb not in next_visit:
            next_visit.append(ngb)
        # もしnon_visitedかつcurrent_colorと異なればnext_visitに追加
        # それ以外は何もしない

    # next_visitが空でないとき
    if len(next_visit) > 0:
        current_position = next_visit.pop(0)
        current_color = colors[current_position]
        groups[current_group][0] += 1-current_color
        groups[current_group][1] += current_color
        unvisited.remove(current_position)
        # next_visitの中から次の移動先を取り出して
        # colorをみてgroupに追加
        # current_positionとcurrent_colorを更新

    elif len(next_visit) == 0:
        # next_visitが空のとき
        if len(unvisited) == 0:
            break
        else:
            current_position = unvisited.pop(0)
            current_color = colors[current_position]
            current_group += 1
            groups[current_group] = [1-current_color, current_color]
            # unvisitedの中から一つ選んで
            # current_position, color更新
            # current_group更新

# print(groups)
ans = 0
for g in groups:
    black, white = groups[g]
    ans += black*white
print(int(ans))

Fixed submission:
import sys
sys.setrecursionlimit(1000000)

h,w=map(int,input().split())
s=[input() for _ in range(h)]
t=[[None]*w for _ in range(h)]

def dfs(i,j,color):

  if not (0<=i<h and 0<=j<w):return 0,0
  if s[i][j]==color: return 0,0
  if t[i][j]:return 0,0

  t[i][j]=True
  wh,bl=0,0
  if s[i][j]=="#":
    bl+=1
  else:
    wh+=1

  tmp1,tmp2=dfs(i+1,j,s[i][j])
  wh,bl=wh+tmp1,bl+tmp2

  tmp1,tmp2=dfs(i-1,j,s[i][j])
  wh,bl=wh+tmp1,bl+tmp2
        
  tmp1,tmp2=dfs(i,j-1,s[i][j])
  wh,bl=wh+tmp1,bl+tmp2

  tmp1,tmp2=dfs(i,j+1,s[i][j])
  wh,bl=wh+tmp1,bl+tmp2

  return wh,bl

ans=0
for i in range(h):
  for j in range(w):
    a,b=dfs(i,j,"!")
    ans+=a*b

print(ans)

Buggy python submission (verdict: Runtime Error):
import numpy as np
h, w = map(int, input().split())
colors = np.zeros((h,w))
for i in range(h):
    s = input()
    for j,c in enumerate(s):
        if c=='#':
            colors[i,j] = 1

def tonari(pos):
    i,j = pos
    ans = []
    if i==0:
        ans.append((i+1,j))
    elif i==h-1:
        ans.append((i-1,j))
    else:
        ans.append((i-1,j))
        ans.append((i+1,j))
    if j==0:
        ans.append((i,j+1))
    elif j==w-1:
        ans.append((i,j-1))
    else:
        ans.append((i,j-1))
        ans.append((i,j+1))
    
    return ans

# 深さ優先探索をする
# マス(0,0)からスタート
# 次の仕切り直しで使うスタート位置のリストnext_start
# すでに訪ねたかどうかを表すh*wの表 visited=1 
# current_positionの前後左右を見てもしcurrent_colorと異なればそっちに動く

current_position = (0,0)
current_color = colors[current_position]
current_group = 0
visited_array = np.zeros((h,w))
visited_array[(0,0)] = 1
groups = {0:[1-current_color, current_color]} # {group_num:(white_num,black_num)}
next_visit = []
other_group = []


while True:
    # current_positionの前後左右を見る
    # print(current_position)
    neighbors = tonari(current_position)
    for ngb in neighbors:
        if colors[ngb] != current_color and visited_array[ngb] == 0 and ngb not in next_visit:
            next_visit.append(ngb)
        # もしnon_visitedかつcurrent_colorと異なればnext_visitに追加
        # それ以外は何もしない

    # next_visitが空でないとき
    if len(next_visit) > 0:
        pos = next_visit.pop(0)
        current_position = pos        
        current_color = colors[current_position]
        groups[current_group][0] += 1-current_color
        groups[current_group][1] += current_color
        visited_array[current_position] = 1
        # next_visitの中から次の移動先を取り出して
        # colorをみてgroupに追加
        # current_positionとcurrent_colorを更新
    elif len(next_visit) == 0:
        # next_visitが空のとき
        row, col = np.where(visited_array==0)
        if len(row) == 0:
            break
        else:
            current_position = (row[0], col[0])
            current_color = colors[current_position]
            current_group += 1
            groups[current_group] = [1-current_color, current_color]
            visited_array[current_position] = 1
            # unvisitedの中から一つ選んで
            # current_position, color更新
            # current_group更新

# print(groups)
ans = 0
for g in groups:
    black, white = groups[g]
    ans += black*white
print(int(ans))



Fixed submission:
import sys
sys.setrecursionlimit(1000000)

h,w=map(int,input().split())
s=[input() for _ in range(h)]
t=[[None]*w for _ in range(h)]

def dfs(i,j,color):

  if not (0<=i<h and 0<=j<w):return 0,0
  if s[i][j]==color: return 0,0
  if t[i][j]:return 0,0

  t[i][j]=True
  wh,bl=0,0
  if s[i][j]=="#":
    bl+=1
  else:
    wh+=1

  tmp1,tmp2=dfs(i+1,j,s[i][j])
  wh,bl=wh+tmp1,bl+tmp2

  tmp1,tmp2=dfs(i-1,j,s[i][j])
  wh,bl=wh+tmp1,bl+tmp2
        
  tmp1,tmp2=dfs(i,j-1,s[i][j])
  wh,bl=wh+tmp1,bl+tmp2

  tmp1,tmp2=dfs(i,j+1,s[i][j])
  wh,bl=wh+tmp1,bl+tmp2

  return wh,bl

ans=0
for i in range(h):
  for j in range(w):
    a,b=dfs(i,j,"!")
    ans+=a*b

print(ans)