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# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using static System.Console;
using static System.Math;
class Z { static void Main() => new K(); }
class K
{
	int F => int.Parse(Str);
	long FL => long.Parse(Str);
	int[] G => Strs.Select(int.Parse).ToArray();
	long[] GL => Strs.Select(long.Parse).ToArray();
	string Str => ReadLine();
	string[] Strs => Str.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
	const int MOD = 1000000007;
	public K()
	{
		SetOut(new StreamWriter(OpenStandardOutput()) { AutoFlush = false });
		Solve();
		Out.Flush();
	}
	int X, Y;
	bool[,] map, flip, done;
	void Solve()
	{
		var I = G;
		Y = I[0]; X = I[1];
		map = new bool[X, Y];
		for (var y = 0; y < Y; y++)
		{
			var S = Str;
			for (var x = 0; x < X; x++) map[x, y] = S[x] == '#';
		}
		flip = new bool[X, Y];
		for (var x = 0; x < X; x++) for (var y = 0; y < Y; y++) flip[x, y] = map[x, y] ^ ((x + y) % 2 != 0);
		done = new bool[X, Y];
		var ans = 0L;
		for (var x = 0; x < X; x++) for (var y = 0; y < Y; y++) ans += Calc(x, y);
		WriteLine(ans);
	}
	int[] dx = { 1, 0, -1, 0, 1 };
	long Calc(int sx, int sy)
	{
		if (done[sx, sy]) return 0;
		var cnt = new int[2];
		var q = new Queue<Tuple<int, int>>();
		q.Enqueue(new Tuple<int, int>(sx, sy));
		var col = flip[sx, sy];
		while (q.Count > 0)
		{
			var p = q.Dequeue();
			if (done[p.Item1, p.Item2]) continue;
			cnt[map[p.Item1, p.Item2] ? 1 : 0]++;
			done[p.Item1, p.Item2] = true;
			for (var i = 0; i < 4; i++)
			{
				var x = p.Item1 + dx[i];
				var y = p.Item2 + dx[i + 1];
				if (x >= 0 && y >= 0 && x < X && y < Y && !done[x, y] && flip[x, y] == col) q.Enqueue(new Tuple<int, int>(x, y));
			}
		}
		return cnt[0] * (long)cnt[1];
	}
}