#include <queue>
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <stack>
#include <string>
#include <vector>
#include <map>
#include <stdio.h>
using namespace std;

#define rep(i, n) for(int i = 0; i < (int)(n); i++)
typedef long long ll;
typedef unsigned long long ull;
typedef vector<ll> vint;
typedef vector<string> vstr;
typedef pair<ll, ll> pint;
unsigned long long inf = (1LL << 62);
ll mod = 1000000007;
        
//bool operator< (pint a, pint b) {
	//return a.second < b.second;

//}
ll gcd(ll a, ll b) {

	if (b == 0)
		return a;

	return gcd(b, a % b);


}

ll max(ll a, ll b) {
	if (a < b) {
		return b;
	}
	else
		return a;

}

ll min(ll a, ll b) {
	if (a < b)
		return a;

	return b;
}




pint dx[4] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1}};

vector<pint> list;










void floyd(int N, ll** d) {

	rep(k, N+1){
		rep(i, N+1) {
			if (d[i+1][k+1] == inf) continue;
			rep(j, N+1) {
				if (d[j+1][k+1] == inf) continue;

				d[i+1][j+1] = min(d[i+1][j+1], d[i+1][k+1] + d[j+1][k+1]);

			}

		}
	}




}


ull modpow(ull a, ull b) {
	ll retval = 0;

	if (b == 0) { return 1; }

	else if (b % 2 == 0) {
		retval = modpow(a, b / 2) % mod;
		return (retval * retval) % mod;
	}

	else {
		
		return ((a % mod) * modpow(a, b - 1)) % mod;
	}
}

ll pow(ll a, ll b){
	ll ret;
	if (b == 0) return 1;
	else if (b % 2 == 0) { ret = pow(a, b / 2); return ret * ret; }
	else if (b % 2 == 1) { return a * pow(a, b - 1); }


}


int bit(ll a, ll n) {
	if (a & pow(2, n-1) != 0) {
		return 1;
	}
	else {
		return 0;
	}
	
	
}

int binary_ketasuu(ll a) {

	int index = 0;

	if (a == 0) {
		return 1;
	}

	while (a - pow(2, index) >= 0) {
		index += 1;
	}
	return index;
}

ull modkaijou(ull a) {

	if (a == 1 || a == 0) { return 1; }

	ll retval = 1;

	for (ull i = a; i >= 1; i--) {
		retval = (retval * (i % mod)) % mod;
	}

	return retval % mod;
}

ull modcomb(ull a, ull b) {

	if (a == 0 || b == 0) return 1;

	return (((modkaijou(a) * modpow(modkaijou(a-b), mod - 2)) % mod) * modpow(modkaijou(b), mod - 2)) % mod;
}


class DisjointSet {
public:
	vector<int> p, rank, num;


	DisjointSet() {}

	DisjointSet(int size) {
		rank.resize(size, 0);
		p.resize(size, 0);
		num.resize(size, 0);
		rep(i, size) { p[i] = i; rank[i] = 0; num[i] = 1; }
	}

	bool same(int x, int y) {

		return findSet(x) == findSet(y);

	}

	void unite(int x, int y) {
		if(!same(x, y))
		link(findSet(x), findSet(y));
	}

	void link(int x, int y) {
		if (rank[x] > rank[y]) {

			p[y] = x;
			num[x] += num[y];

		}

		else {
			p[x] = y;
			num[y] += num[x];
			if (rank[x] == rank[y]) {

				rank[y]++;
			}

		}


	}


	ll NumberOfElements(int x) {

		return num[findSet(x)];

	}


	int findSet(int x) {
		if (x != p[x]) {
			p[x] = findSet(p[x]);
			num[x] = 1;
		}

		return p[x];
	}



};


bool compare_b(pint a, pint b) {
	if (a.first < b.first) {
		return true;
	}
	else if (a.first == b.first) {
		return a.second < b.second;
	}

	else {
		return false;
	}

}


int ketasuu(int a) {

	int ret = 1;
	int val = a;
	while (val / 10 != 0) {

		ret += 1;
		val /= 10;
	}
	return ret;
}

typedef struct trio {
	ll a, b, y;
}ti;


string to_binary(ll a) {
	ll val = a;
	string retval = "";

	retval = to_string(val % 2);
	while (val / 2 != 0) {
		val /= 2;
		retval = (to_string(val % 2)) + retval;

	}

	
	


	return retval;
}

int ctoi(char a) {

	return a - '0';
}








char ma[405][405];
ll ans = 0;
queue<pint> q;

int vis[405][405], dist[405][405];
ll num_sh = 0, num_dot = 0;

void bfs(int m, int n) {

	int x, y;
	int nextx, nexty;
	q.push({ m, n });




	num_sh += 1;


	while (q.size() != 0) {

		x = q.front().first;
		y = q.front().second;
		vis[x][y] = 1;
		q.pop();
		rep(i, 4) {
			
				nextx = x + dx[i].first;
				nexty = y + dx[i].second;

				if (ma[nextx][nexty] == '.' && vis[nextx][nexty] == 0 && (dist[x][y] + 1) % 2 == 1) {
					dist[nextx][nexty] = dist[x][y] + 1; 
					vis[nextx][nexty] = 1;
					q.push({nextx, nexty});
					num_dot += 1;
			    }
				else if (ma[nextx][nexty] == '#' && vis[nextx][nexty] == 0 && (dist[x][y] + 1) % 2 == 0) {
					dist[nextx][nexty] = dist[x][y] +  1;
					vis[nextx][nexty] = 1;
					q.push({ nextx, nexty });
					num_sh += 1;
				}

		}

		

	}

}



int main() {
	ll H, W;
	
	cin >> H >> W;

	rep(i, H) {
		ma[i][0] = 'x';
		ma[i][W + 1] = 'x';
	}
	rep(i, W) {
		ma[0][i] = 'x';
		ma[H + 1][i] = 'x';
	}

	rep(i, H) {
		rep(j, W) { cin >> ma[i + 1][j + 1]; }
	}


	rep(i, H) {
		rep(j, W) {
			if (ma[i + 1][j + 1] == '#' && vis[i+1][j+1] == 0) {


				
				bfs(i + 1, j + 1);
				ans += num_sh * num_dot;
				num_sh = 0; num_dot = 0;
			}
		}
	}

	cout << ans << endl;

	return 0;
}

Measured memory_bytes: 1664