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 Perl (v5.18.2) (judge verdict: Time Limit Exceeded)

use v5.18;
use warnings;
use List::Util qw( sum );
sub read_line { chomp(my $s = <>); $s }
sub splited_read_line { split / /, read_line }
sub unique { my %u; $u{$_} = $_ for @_; values %u; }

package UnionFind {

  sub new {
    my ($class, $n) = @_;
    bless [ 0 .. $n - 1 ], $class;
  }

  sub root {
    my ($self, $x) = @_;
    if ( $self->[$x] == $x ) {
      $x;
    }
    else {
      $self->[$x] = $self->root($self->[$x]);
    }
  }

  sub unite {
    my ($self, $x, $y) = @_;
    my ($x_root, $y_root) = ($self->root($x), $self->root($y));
    if ( $x_root == $y_root ) {
      return;
    }
    else {
      $self->[$x_root] = $y_root;
    }
  }

  sub is_same {
    my ($self, $x, $y) = @_;
    $self->root($x) == $self->root($y);
  }

  sub compression {
    my $self = shift;
    $self->root($_) for 0 .. $#$self;
  }

}

my ($h, $w) = splited_read_line;
my $mass = [ map { [ split //, read_line ] } 0 .. $h - 1 ];
say solve($h, $w, $mass);

sub solve {
  my ($h, $w, $mass) = @_;
  my $tree = UnionFind->new($h * $w);
  for my $y (0 .. $h - 1) {
    for my $x (0 .. $w - 1) {
      my $current        = $y * $w + $x;
      my $current_coloor = $mass->[$y][$x];
      next if $current_coloor eq '.';
      my $points = [
        [ $y + 1, $x ],
        [ $y - 1, $x ],
        [ $y, $x + 1 ],
        [ $y, $x - 1 ],
      ];
      for my $point (@$points) {
        my ($y, $x) = @$point;
        if (
          $y < $h && $y >= 0 && $x < $w && $x >= 0 &&
          $current_coloor ne $mass->[$y][$x]
        ) {
          $tree->unite($y * $w + $x, $current);
        }
      }
    }
  }
  $tree->compression;
  my @vertexes = unique @$tree;
  sum map {
    my $vertex = $_;
    my @points = grep { $vertex == $tree->[$_] } 0 .. $#$tree;
    my $colors = join '', map {
      my $y = int($_ / $w);
      my $x = $_ % $w;
      $mass->[$y][$x];
    } @points;
    my $black = () = $colors =~ /#/g;
    my $white = () = $colors =~ /\./g;
    $black * $white;
  } @vertexes;
}