from collections import defaultdict



H,W = list(map(int, input().split()))

S = [eval(input()) for _ in range(H)]



es = defaultdict(list)

for i in range(H):

    for j in range(W):

        # 横

        if j != W-1 and S[i][j] != S[i][j+1]:

            es[(i,j)].append((i,j+1))

            es[(i,j+1)].append((i,j))



        # 縦

        if i != H-1 and S[i][j] != S[i+1][j]:

            es[(i,j)].append((i+1,j))

            es[(i+1,j)].append((i,j))





ans = 0

checked = [[False for _ in range(W)] for _ in range(H)]



stack  = list(es.keys())

for i,j in stack:

    # 開始位置

    if checked[i][j]:

        continue

    

    if S[i][j] == "#":

        cnt_b = 1

        cnt_w = 0

    else:

        cnt_b = 0

        cnt_w = 1





    checked[i][j] = True

    ns = es[(i,j)]

    #tmp = []

    while ns:

        tmp = []

        for a,b in ns:

            if checked[a][b] == True: continue



            checked[a][b] = True

            if S[a][b] == "#":

                cnt_b += 1

            else:

                cnt_w += 1



            for c,d in es[(a,b)]:

                if not checked[c][d]:

                    tmp.append((c,d))

        if len(tmp) > 0:

            ns = tmp

        else:

            ns = []            

    ans += cnt_b * cnt_w





print(ans)

from collections import Counter



H,W = list(map(int, input().split()))

S = [eval(input()) for _ in range(H)]





 

class UnionFind:

    def __init__(self,N):

        self.parent = [i for i in range(N)]

        self.rank = [0] * N

        self.count = 0

    def root(self,a):

        if self.parent[a] == a:

            return a

        else:

            self.parent[a] = self.root(self.parent[a])

            return self.parent[a]

    def is_same(self,a,b):

        return self.root(a) == self.root(b)

    def unite(self,a,b):

        ra = self.root(a)

        rb = self.root(b)

        if ra == rb: return

        if self.rank[ra] < self.rank[rb]:

            self.parent[ra] = rb

        else:

            self.parent[rb] = ra

            if self.rank[ra] == self.rank[rb]: self.rank[ra] += 1

        self.count += 1



uf = UnionFind(H*W)



for i in range(H):

    for j in range(W):

        

        # 横

        if j != W-1 and S[i][j] != S[i][j+1]:

            uf.unite(i*W+j, i*W+j+1)

        

        # 縦

        if i != H-1 and S[i][j] != S[i+1][j]:

            uf.unite(i*W+j, (i+1)*W+j)



for i in range(H*W):

    uf.root(i)



black = Counter()

white = Counter()



#あるユニオンに所属（#.#.の移動できる塊）の#と.の数を数える

for i in range(H):

    for j in range(W):

        k = i*W+j

        if S[i][j] == "#":

            black[uf.root(k)] += 1

        else:

            white[uf.root(k)] += 1



#ユニオンごとに足し合わせ

ans = 0

for k in list(black.keys()):

    ans += black[k] * white[k]



print(ans)
from collections import defaultdict

H, W = list(map(int, input().split()))
S = [eval(input()) for _ in range(H)]
es = defaultdict(list)
for i in range(H):
    for j in range(W):
        # 横
        if j != W - 1 and S[i][j] != S[i][j + 1]:
            es[(i, j)].append((i, j + 1))
            es[(i, j + 1)].append((i, j))
        # 縦
        if i != H - 1 and S[i][j] != S[i + 1][j]:
            es[(i, j)].append((i + 1, j))
            es[(i + 1, j)].append((i, j))
ans = 0
checked = [[False for _ in range(W)] for _ in range(H)]
stack = list(es.keys())
for i, j in stack:
    # 開始位置
    if checked[i][j]:
        continue
    if S[i][j] == "#":
        cnt_b = 1
        cnt_w = 0
    else:
        cnt_b = 0
        cnt_w = 1
    checked[i][j] = True
    ns = es[(i, j)]
    # tmp = []
    while ns:
        tmp = []
        for a, b in ns:
            if checked[a][b] == True:
                continue
            checked[a][b] = True
            if S[a][b] == "#":
                cnt_b += 1
            else:
                cnt_w += 1
            for c, d in es[(a, b)]:
                if not checked[c][d]:
                    tmp.append((c, d))
        if len(tmp) > 0:
            ns = tmp
        else:
            ns = []
    ans += cnt_b * cnt_w
print(ans)

from collections import Counter

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


class UnionFind:
    def __init__(self, N):
        self.parent = [i for i in range(N)]
        self.rank = [0] * N
        self.count = 0

    def root(self, a):
        if self.parent[a] == a:
            return a
        else:
            self.parent[a] = self.root(self.parent[a])
            return self.parent[a]

    def is_same(self, a, b):
        return self.root(a) == self.root(b)

    def unite(self, a, b):
        ra = self.root(a)
        rb = self.root(b)
        if ra == rb:
            return
        if self.rank[ra] < self.rank[rb]:
            self.parent[ra] = rb
        else:
            self.parent[rb] = ra
            if self.rank[ra] == self.rank[rb]:
                self.rank[ra] += 1
        self.count += 1


uf = UnionFind(H * W)
for i in range(H):
    for j in range(W):
        # 横
        if j != W - 1 and S[i][j] != S[i][j + 1]:
            uf.unite(i * W + j, i * W + j + 1)
        # 縦
        if i != H - 1 and S[i][j] != S[i + 1][j]:
            uf.unite(i * W + j, (i + 1) * W + j)
for i in range(H * W):
    uf.root(i)
black = Counter()
white = Counter()
# あるユニオンに所属（#.#.の移動できる塊）の#と.の数を数える
for i in range(H):
    for j in range(W):
        k = i * W + j
        if S[i][j] == "#":
            black[uf.root(k)] += 1
        else:
            white[uf.root(k)] += 1
# ユニオンごとに足し合わせ
ans = 0
for k in list(black.keys()):
    ans += black[k] * white[k]
print(ans)

-from collections import defaultdict +from collections import Counter -es = defaultdict(list) + + +class UnionFind: +    def __init__(self, N): +        self.parent = [i for i in range(N)] +        self.rank = [0] * N +        self.count = 0 + +    def root(self, a): +        if self.parent[a] == a: +            return a +        else: +            self.parent[a] = self.root(self.parent[a]) +            return self.parent[a] + +    def is_same(self, a, b): +        return self.root(a) == self.root(b) + +    def unite(self, a, b): +        ra = self.root(a) +        rb = self.root(b) +        if ra == rb: +            return +        if self.rank[ra] < self.rank[rb]: +            self.parent[ra] = rb +        else: +            self.parent[rb] = ra +            if self.rank[ra] == self.rank[rb]: +                self.rank[ra] += 1 +        self.count += 1 + + +uf = UnionFind(H * W) -            es[(i, j)].append((i, j + 1)) -            es[(i, j + 1)].append((i, j)) +            uf.unite(i * W + j, i * W + j + 1) -            es[(i, j)].append((i + 1, j)) -            es[(i + 1, j)].append((i, j)) +            uf.unite(i * W + j, (i + 1) * W + j) +for i in range(H * W): +    uf.root(i) +black = Counter() +white = Counter() +# あるユニオンに所属（#.#.の移動できる塊）の#と.の数を数える +for i in range(H): +    for j in range(W): +        k = i * W + j +        if S[i][j] == "#": +            black[uf.root(k)] += 1 +        else: +            white[uf.root(k)] += 1 +# ユニオンごとに足し合わせ -checked = [[False for _ in range(W)] for _ in range(H)] -stack = list(es.keys()) -for i, j in stack: -    # 開始位置 -    if checked[i][j]: -        continue -    if S[i][j] == "#": -        cnt_b = 1 -        cnt_w = 0 -    else: -        cnt_b = 0 -        cnt_w = 1 -    checked[i][j] = True -    ns = es[(i, j)] -    # tmp = [] -    while ns: -        tmp = [] -        for a, b in ns: -            if checked[a][b] == True: -                continue -            checked[a][b] = True -            if S[a][b] == "#": -                cnt_b += 1 -            else: -                cnt_w += 1 -            for c, d in es[(a, b)]: -                if not checked[c][d]: -                    tmp.append((c, d)) -        if len(tmp) > 0: -            ns = tmp -        else: -            ns = [] -    ans += cnt_b * cnt_w +for k in list(black.keys()): +    ans += black[k] * white[k]