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: Time Limit Exceeded)

using System;
using System.Collections.Generic;
using static System.Console;

namespace C
{
  class Program
  {
    static int X = 0;
    static int Y = 1;

    static void Main(string[] args)
    {
      string[] input = ReadLine().Split();
      int H = int.Parse(input[0]);
      int W = int.Parse(input[1]);


      bool[,] isLook = new bool[W, H];
      bool[,] table = new bool[W, H];

      var bcell = new List<int[]>();
      var wcell = new List<int[]>();

      for(int h = 0; h<H; h++) {
        string S = ReadLine();
        for(int w = 0; w<W; w++) {
          table[w, h] = S[w] == '.';
          if(S[w] == '.') wcell.Add(new int[] { w, h });
          else bcell.Add(new int[] { w, h });
        }
      }

      int count = 0;
      foreach(var black in bcell)
        foreach(var white in wcell) {
          if(Walk(H, W, black, white, black, isLook, table)) count++;
          isLook = new bool[W, H];
        }

      WriteLine(count);
    }

    static bool Walk(int H, int W, int[] black, int[] white, int[] now, bool[,] isLook, bool[,] table)
    {
      if(isLook[now[X], now[Y]]) return false;
      isLook[now[X], now[Y]] = true;
      if(now[X] == white[X] && now[Y] == white[Y])
        return true;
      
      // up
      if(now[Y] > 0)
        if(table[now[X], now[Y]] != table[now[X], now[Y]-1])
          if(Walk(H, W, black, white, new int[] { now[X], now[Y]-1 }, isLook, table))
            return true;
      // down
      if(now[Y] < H-1)
        if(table[now[X], now[Y]] != table[now[X], now[Y]+1])
          if(Walk(H, W, black, white, new int[] { now[X], now[Y]+1 }, isLook, table))
            return true;
      // left
      if(now[X] > 0)
        if(table[now[X], now[Y]] != table[now[X]-1, now[Y]])
          if(Walk(H, W, black, white, new int[] { now[X]-1, now[Y] }, isLook, table))
            return true;
      // right
      if(now[X] < W-1)
        if(table[now[X], now[Y]] != table[now[X]+1, now[Y]])
          if(Walk(H, W, black, white, new int[] { now[X]+1, now[Y] }, isLook, table))
            return true;

      return false;
    }
  }
}