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 Rust (1.15.1) (judge verdict: Accepted)

fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>().split_whitespace()
        .map(|e| e.parse().ok().unwrap()).collect()
}

fn dfs(i: usize, j: usize, field: &mut Vec<Vec<char>>, is_checked: &mut Vec<Vec<bool>>) -> u64 {
    let mut stack = std::collections::VecDeque::new();
    stack.push_back((i, j));
    let mut black_count = 0;
    let mut white_count = 0;
    is_checked[i][j] = true;
    while let Some((cur_x, cur_y)) = stack.pop_back() {
        if field[cur_x][cur_y] == '#' {
            black_count += 1;
        } else {
            white_count += 1;
        }
        if cur_x > 0 && field[cur_x - 1][cur_y] != field[cur_x][cur_y] && !is_checked[cur_x - 1][cur_y] {
            is_checked[cur_x - 1][cur_y] = true;
            stack.push_back((cur_x - 1, cur_y));
        }
        if cur_x < field.len() - 1 && field[cur_x + 1][cur_y] != field[cur_x][cur_y] && !is_checked[cur_x + 1][cur_y] {
            is_checked[cur_x + 1][cur_y] = true;
            stack.push_back((cur_x + 1, cur_y));
        }
        if cur_y > 0 && field[cur_x][cur_y - 1] != field[cur_x][cur_y] && !is_checked[cur_x][cur_y - 1] {
            is_checked[cur_x][cur_y - 1] = true;
            stack.push_back((cur_x, cur_y - 1));
        }
        if cur_y < field[0].len() - 1 && field[cur_x][cur_y + 1] != field[cur_x][cur_y] && !is_checked[cur_x][cur_y + 1] {
            is_checked[cur_x][cur_y + 1] = true;
            stack.push_back((cur_x, cur_y + 1));
        }
    }
    // println!("{:?}", (black_count, white_count));
    black_count * white_count
}

fn main() {
    let v = read_vec::<usize>();
    let (h, w) = (v[0], v[1]);

    let mut field = (0..h)
        .map(|_| read::<String>().chars().collect::<Vec<_>>())
        .collect::<Vec<_>>();

    let mut is_checked: Vec<Vec<bool>> = vec![vec![false; w]; h];

    let mut ans = 0u64;
    for i in 0..field.len() {
        for j in 0..field[0].len() {
            if field[i][j] == '#' && !is_checked[i][j] {
                ans += dfs(i, j, &mut field, &mut is_checked);
            }
        }
    }
    println!("{:?}", ans);
}