#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>
#include <climits>
#include <algorithm>
#include <cassert>
#include <vector>
#include <array>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <stack>
#include <queue>
#include <numeric>
#define ALL(c) (c).begin(), (c).end()

using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdi = pair<double, int>;
using pdd = pair<double, double>;

#pragma once
#include <utility>
#include <iostream>

using pii = std::pair<int, int>;

long long pair_to_int(pii p, pii whole_size_pair);
pii int_to_pair(long long x, pii whole_size_pair);
pii whole_size_pair;

//----------------------------------------------------------
using namespace std;

void set_whole_size_pair(pii p){
	whole_size_pair = p;
}
void set_whole_size_pair(int x, int y) {
	set_whole_size_pair(pii(x, y));
}

long long pair_to_int(pii p, pii whole_size_pair) { //whole_size_pairについて：計算に使うのはpairの2個目の繰り上がり値（最大値+1)だけ
	if (p.first < whole_size_pair.first && p.second < whole_size_pair.second)
		return (long long)(p.first)*whole_size_pair.second + p.second;
	else {
		cout << "error in pair_to_int" << endl;
		exit(1);
	}
}

long long pair_to_int(pii p) { //whole_size_pairについて：計算に使うのはpairの2個目の繰り上がり値（最大値+1)だけ
	if (p.first < whole_size_pair.first && p.second < whole_size_pair.second)
		return (long long)(p.first)*whole_size_pair.second + p.second;
	else {
		cout << "error in pair_to_int" << endl;
		exit(1);
	}
}

long long pair_to_int(int x, int y) { //whole_size_pairについて：計算に使うのはpairの2個目の繰り上がり値（最大値+1)だけ
	return pair_to_int(pii(x, y));
}

pii int_to_pair(long long x, pii whole_size_pair) {
	if (x < (long long)(whole_size_pair.first) * whole_size_pair.second) //wholeSizePairについて：計算に使うのはpairの2個目の繰り上がり値（最大値+1)だけ
		return pii((int)(x / whole_size_pair.second), (int)(x % whole_size_pair.second));
	else {
		cout << "error in int_to_pair" << endl;
		exit(1);
	}
}
pii int_to_pair(long long x) {
	if (x < (long long)(whole_size_pair.first) * whole_size_pair.second) //wholeSizePairについて：計算に使うのはpairの2個目の繰り上がり値（最大値+1)だけ
		return pii((int)(x / whole_size_pair.second), (int)(x % whole_size_pair.second));
	else {
		cout << "error in int_to_pair" << endl;
		exit(1);
	}
}
int H, W;

struct UnionFind {
	vector<pii> data;
	UnionFind(int size, vector<string> s) : data(size, pii(-1, 0)) {
		for (int i = 0; i < H; i++)
		{
			for (int j = 0; j < W; j++)
			{
				if (s[i][j] == '#') {
					data[pair_to_int(i, j)].second = 1;
				}
			}
		}
		//for (int l = 0; l < size; l++)
		//{
		//	if (s[int_to_pair((ll)l).first][int_to_pair((ll)l).second] == '#') {
		//		data[l].second = 1;
		//	}
		//}
	}
	bool unionSet(int x, int y) {
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y].first < data[x].first) swap(x, y);
			data[x].first += data[y].first;
			data[x].second += data[y].second;
			data[y].first = x;
		}
		return x != y;
	}
	bool findSet(int x, int y) {
		return root(x) == root(y);
	}
	int root(int x) {
		return data[x].first < 0 ? x : data[x].first = root(data[x].first);
	}
	int size(int x) {
		return -data[root(x)].first;
	}
	int size_black(int x) {
		return data[root(x)].second;
	}
};

vector<string> S;

int main() {
	cin >> H >> W;
	for (int i = 0; i < H; i++)
	{
		string tmpS;
		cin >> tmpS;
		S.push_back(tmpS);
	}
	const int nd = 2;
	pii d[nd] = { {-1,0}, {0,-1} };
	set_whole_size_pair(H, W);
	UnionFind uf(H * W, S);
	for (int i = 0; i < H; i++)
	{
		for (int j = 0; j < W; j++)
		{
			char anotherc;
			if (S[i][j] == '#') {
				anotherc = '.';
			}
			else {
				anotherc = '#';
			}
			for (int k = 0; k < nd; k++)
			{
				const int ti = i + d[k].first, tj = j + d[k].second;
				if (0 <= ti and 0 <= tj and S[ti][tj] == anotherc) {
					uf.unionSet(pair_to_int(i, j), pair_to_int(ti, tj));
				}
			}
		}
	}
	unordered_set<int> us;
	ll ans = 0;
	for (int i = 0; i < H; i++)
	{
		for (int j = 0; j < W; j++)
		{
			const int ij = (int)pair_to_int(pii(i, j));
			if (us.find(uf.root(ij)) != us.end())
				continue;
			const int nb = uf.size_black(ij), nw = uf.size(ij) - nb;
			ans += (ll)nb * nw;
			us.insert(uf.root(ij));
		}
	}
	cout << ans << endl;
	return 0;
}



Measured memory_bytes: 8460