Problem:
Score : 300 points

Problem Statement

There is a grid with H rows and W columns, where each square is painted black or white.

You are given H strings S_1, S_2, ..., S_H, each of length W.
If the square at the i-th row from the top and the j-th column from the left is painted black, the j-th character in the string S_i is #; if that square is painted white, the j-th character in the string S_i is ..

Find the number of pairs of a black square c_1 and a white square c_2 that satisfy the following condition:

There is a path from the square c_1 to the square c_2 where we repeatedly move to a vertically or horizontally adjacent square through an alternating sequence of black and white squares: black, white, black, white...

Constraints

1 \leq H, W \leq 400

|S_i| = W (1 \leq i \leq H)

For each i (1 \leq i \leq H), the string S_i consists of characters # and ..

Input

Input is given from Standard Input in the following format:

H W
S_1
S_2
:
S_H

Output

Print the answer.

Sample Input 1

3 3
.#.
..#
#..

Sample Output 1

10

Some of the pairs satisfying the condition are ((1, 2), (3, 3)) and ((3, 1), (3, 2)), where (i, j) denotes the square at the i-th row from the top and the j-th column from the left.

Sample Input 2

2 4
....
....

Sample Output 2

0

Sample Input 3

4 3
###
###
...
###

Sample Output 3

6

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>

#define REP(i, s,  n) for(int i = s;i < (n);i++)
#define VSORT(v) sort(v.begin(), v.end());
#define int64 long long
#define pb(a) push_back(a)
#define REP64(i, s,  n) for(int64 i = s;i < (n);i++)
#define INF 999999999
#define MOD 1000000007
using namespace std;

typedef pair<int, int> P;
typedef pair<int, P> PP;

template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }

int dy[]={0, 0, 1, -1, 0};
int dx[]={1, -1, 0, 0, 0};

//---------------------------------------------------------------
// C_2 と同じテストケースでエラーとなる・・・
//---------------------------------------------------------------

int H, W;
char C[500][500];
int M[500][500];		// 処理済みなら　１
stack<P> S;				// スタック

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> H >> W;
	REP(i, 0, H)	cin >> C[i];

	int64 ans = 0;
	REP(i, 0, H)	REP(j, 0, W) {
		S.push( P(i,j) );			// スタートをスタックに積む

		int64 b = 0;
		int64 w = 0;
		while(!S.empty()) {				// スタックが空になるまで（スタートから届く範囲だけ処理する）
			P p = S.top(); S.pop();
			int ii = p.first;
			int jj = p.second;
			if(M[ii][jj] != 0)	continue;
			M[ii][jj] = 1;				// 処理済みとする
			if(C[ii][jj] == '#')	b++;
			else					w++;

										// 処理していなければ、スタックに積む
			if(ii > 0     && C[ii][jj] != C[ii-1][jj])	S.push( P(ii-1, jj) );
			if(ii < H - 1 && C[ii][jj] != C[ii+1][jj])	S.push( P(ii+1, jj) );
			if(jj > 0     && C[ii][jj] != C[ii][jj-1])	S.push( P(ii, jj-1) );
			if(jj < W - 1 && C[ii][jj] != C[ii][jj+1])	S.push( P(ii, jj+1) );
		}
		ans += b * w;
	}
	
	cout << ans << endl;

	return 0;
}