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: Wrong Answer)

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <sstream>
#include <algorithm>
#include <cstdlib>
#include <map>
#include <queue>
#include <utility>
#include <vector>
#include <set>
#include <memory.h>
#include <iomanip>
#include <bitset>
#include <list>
#include <stack>
#include <deque>
#include <numeric>

using namespace std;

#define mod 1000000007

class UF
{
private:
	vector<int> root;
	vector<int> black;
	vector<int> white;

public:
	UF(int n)
	{
		root = vector<int>(n, -1);
		black = vector<int>(n, 0);
		white = vector<int>(n, 0);
	}

	int getRoot(int x)
	{
		if(root[x] == -1) return x;
		else return root[x] = getRoot(root[x]);
	}

	int getBlack(int x)
	{
		return black[getRoot(x)];
	}

	int getWhite(int x)
	{
		return white[getRoot(x)];
	}

	void update(int x, int y)
	{
		x = getRoot(x);
		y = getRoot(y);
		if(x == y) return;
		// if(x > y) swap(x, y);
		root[y] = x;
		black[x] += black[y];
		white[x] += white[y];
	}

	void addBlack(int x)
	{
		black[x]++;
	}

	void addWhite(int x)
	{
		white[x]++;
	}

};

int main()
{
	int h, w;
	cin >> h >> w;
	UF uf(h * w);
	char s[401][401];
	for(int i = 0; i < h; i++){
		for(int j = 0; j < w; j++){
			cin >> s[i][j];
			if(s[i][j] == '.') uf.addWhite(w * i + j);
			else uf.addBlack(w * i + j);
		}
	}

	int dx[2] = {1, 0};
	int dy[2] = {0, 1};
	for(int i = 0; i < h; i++){
		for(int j = 0; j < w; j++){
			for(int k = 0; k < 2; k++){
				int nx = i + dx[k];
				int ny = j + dy[k];
				if(nx >= h || ny >= w) continue;
				if(s[i][j] != s[nx][ny]){
					uf.update(i * w + j, nx * w + ny);
				}
			}
		}
	}
	long long int ans = 0;
	for(int i = 0; i < h * w; i++){
		// cout << uf.getRoot(i) << " " << uf.getBlack(i) << " " << uf.getWhite(i) << endl;
		if(uf.getRoot(i) == i) ans += uf.getBlack(i) * uf.getWhite(i);
	}
	cout << ans << endl;
}