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

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

N=H*W

par=[0 for i in range(N)]

rnk=[0 for i in range(N)]

def init(n):

    for i in range(N):

        par[i]=i

        rnk[i]=0

def find(x):

    if par[x]==x:

        return x

    else:

        par[x]=find(par[x])

        return par[x]

def unite(x,y):

    x=find(x)

    y=find(y)

    if x==y:

        return

    if (rnk[x]<rnk[y]):

        par[x]=y

    else:

        par[y]=x

        if(rnk[x]==rnk[y]):

            rnk[x]+=1

def same(x,y):

    return find(x)==find(y)

init(N)

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

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

for i in range(H):

    for j in range(W):

        for k in range(4):

            nx=dx[k]+i

            ny=dy[k]+j

            if 0<=nx<H and 0<=ny<W:

                if S[nx][ny]!=S[i][j]:

                    p=i*W+j

                    q=nx*W+ny

                    unite(p,q)

A=[find(i) for i in range(N)]

D=dict()

for j in range(N):

    i=A[j]

    if not(i in D):

        D[i]=[0,0]

    if S[j//W][j%W]=="#":

        D[i][1]+=1

    else:

        D[i][0]+=1

ans=0

for i in D:

    seq=D[i]

    ans+=seq[0]*seq[1]

print(ans)

class UnionFind():

    n=1

    par=[0]

    rnk=[0]

    def __init__(self,size):

        self.n=size

        self.par=[i for i in range(self.n)]

        self.rnk=[0 for i in range(self.n)]

    def find(self,vertex1):

        if self.par[vertex1]==vertex1:

            return vertex1

        else:

            self.par[vertex1]=self.find(self.par[vertex1])

            return self.par[vertex1]

    def unite(self,vertex1,vertex2):

        vertex1=self.find(vertex1)

        vertex2=self.find(vertex2)

        if vertex1==vertex2:

            return

        if (self.rnk[vertex1]<self.rnk[vertex2]):

            self.par[vertex1]=vertex2

        else:

            self.par[vertex2]=vertex1

            if(self.rnk[vertex1]==self.rnk[vertex2]):

                self.rnk[vertex1]+=1

    def same(self,vetrex1,vertex2):

        return self.find(vetrex1)==self.find(vertex2)

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

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

G=UnionFind(H*W)

#i*W+j

for i in range(H):

    for j in range(W-1):

        if S[i][j]!=S[i][j+1]:

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

for i in range(H-1):

    for j in range(W):

        if S[i][j]!=S[i+1][j]:

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

D=dict()

for i in range(H):

    for j in range(W):

        k=G.find(i*W+j)

        if not k in D:

            D[k]=[0,0]

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

            D[k][0]+=1

        else:

            D[k][1]+=1

ans=0

for k in D:

    x=D[k][0]

    y=D[k][1]

    ans+=x*y

print(ans)

H, W = list(map(int, input().split()))
S = [list(eval(input())) for i in range(H)]
N = H * W
par = [0 for i in range(N)]
rnk = [0 for i in range(N)]


def init(n):
    for i in range(N):
        par[i] = i
        rnk[i] = 0


def find(x):
    if par[x] == x:
        return x
    else:
        par[x] = find(par[x])
        return par[x]


def unite(x, y):
    x = find(x)
    y = find(y)
    if x == y:
        return
    if rnk[x] < rnk[y]:
        par[x] = y
    else:
        par[y] = x
        if rnk[x] == rnk[y]:
            rnk[x] += 1


def same(x, y):
    return find(x) == find(y)


init(N)
dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]
for i in range(H):
    for j in range(W):
        for k in range(4):
            nx = dx[k] + i
            ny = dy[k] + j
            if 0 <= nx < H and 0 <= ny < W:
                if S[nx][ny] != S[i][j]:
                    p = i * W + j
                    q = nx * W + ny
                    unite(p, q)
A = [find(i) for i in range(N)]
D = dict()
for j in range(N):
    i = A[j]
    if not (i in D):
        D[i] = [0, 0]
    if S[j // W][j % W] == "#":
        D[i][1] += 1
    else:
        D[i][0] += 1
ans = 0
for i in D:
    seq = D[i]
    ans += seq[0] * seq[1]
print(ans)

class UnionFind:
    n = 1
    par = [0]
    rnk = [0]

    def __init__(self, size):
        self.n = size
        self.par = [i for i in range(self.n)]
        self.rnk = [0 for i in range(self.n)]

    def find(self, vertex1):
        if self.par[vertex1] == vertex1:
            return vertex1
        else:
            self.par[vertex1] = self.find(self.par[vertex1])
            return self.par[vertex1]

    def unite(self, vertex1, vertex2):
        vertex1 = self.find(vertex1)
        vertex2 = self.find(vertex2)
        if vertex1 == vertex2:
            return
        if self.rnk[vertex1] < self.rnk[vertex2]:
            self.par[vertex1] = vertex2
        else:
            self.par[vertex2] = vertex1
            if self.rnk[vertex1] == self.rnk[vertex2]:
                self.rnk[vertex1] += 1

    def same(self, vetrex1, vertex2):
        return self.find(vetrex1) == self.find(vertex2)


H, W = list(map(int, input().split()))
S = [list(eval(input())) for i in range(H)]
G = UnionFind(H * W)
# i*W+j
for i in range(H):
    for j in range(W - 1):
        if S[i][j] != S[i][j + 1]:
            G.unite(i * W + j, i * W + (j + 1))
for i in range(H - 1):
    for j in range(W):
        if S[i][j] != S[i + 1][j]:
            G.unite(i * W + j, (i + 1) * W + j)
D = dict()
for i in range(H):
    for j in range(W):
        k = G.find(i * W + j)
        if not k in D:
            D[k] = [0, 0]
        if S[i][j] == "#":
            D[k][0] += 1
        else:
            D[k][1] += 1
ans = 0
for k in D:
    x = D[k][0]
    y = D[k][1]
    ans += x * y
print(ans)

+class UnionFind: +    n = 1 +    par = [0] +    rnk = [0] + +    def __init__(self, size): +        self.n = size +        self.par = [i for i in range(self.n)] +        self.rnk = [0 for i in range(self.n)] + +    def find(self, vertex1): +        if self.par[vertex1] == vertex1: +            return vertex1 +        else: +            self.par[vertex1] = self.find(self.par[vertex1]) +            return self.par[vertex1] + +    def unite(self, vertex1, vertex2): +        vertex1 = self.find(vertex1) +        vertex2 = self.find(vertex2) +        if vertex1 == vertex2: +            return +        if self.rnk[vertex1] < self.rnk[vertex2]: +            self.par[vertex1] = vertex2 +        else: +            self.par[vertex2] = vertex1 +            if self.rnk[vertex1] == self.rnk[vertex2]: +                self.rnk[vertex1] += 1 + +    def same(self, vetrex1, vertex2): +        return self.find(vetrex1) == self.find(vertex2) + + -N = H * W -par = [0 for i in range(N)] -rnk = [0 for i in range(N)] - - -def init(n): -    for i in range(N): -        par[i] = i -        rnk[i] = 0 - - -def find(x): -    if par[x] == x: -        return x -    else: -        par[x] = find(par[x]) -        return par[x] - - -def unite(x, y): -    x = find(x) -    y = find(y) -    if x == y: -        return -    if rnk[x] < rnk[y]: -        par[x] = y -    else: -        par[y] = x -        if rnk[x] == rnk[y]: -            rnk[x] += 1 - - -def same(x, y): -    return find(x) == find(y) - - -init(N) -dx = [0, 0, 1, -1] -dy = [1, -1, 0, 0] +G = UnionFind(H * W) +# i*W+j +for i in range(H): +    for j in range(W - 1): +        if S[i][j] != S[i][j + 1]: +            G.unite(i * W + j, i * W + (j + 1)) +for i in range(H - 1): +    for j in range(W): +        if S[i][j] != S[i + 1][j]: +            G.unite(i * W + j, (i + 1) * W + j) +D = dict() -        for k in range(4): -            nx = dx[k] + i -            ny = dy[k] + j -            if 0 <= nx < H and 0 <= ny < W: -                if S[nx][ny] != S[i][j]: -                    p = i * W + j -                    q = nx * W + ny -                    unite(p, q) -A = [find(i) for i in range(N)] -D = dict() -for j in range(N): -    i = A[j] -    if not (i in D): -        D[i] = [0, 0] -    if S[j // W][j % W] == "#": -        D[i][1] += 1 -    else: -        D[i][0] += 1 +        k = G.find(i * W + j) +        if not k in D: +            D[k] = [0, 0] +        if S[i][j] == "#": +            D[k][0] += 1 +        else: +            D[k][1] += 1 -for i in D: -    seq = D[i] -    ans += seq[0] * seq[1] +for k in D: +    x = D[k][0] +    y = D[k][1] +    ans += x * y