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.42.0) (judge verdict: Accepted)

use std::cmp;
use std::collections::VecDeque;
use std::fmt::Debug;
use std::str::FromStr;

#[allow(dead_code)]
fn read_as_vec<T>() -> Vec<T>
where
    T: FromStr,
    <T as FromStr>::Err: Debug,
{
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    s.trim()
        .split_whitespace()
        .map(|c| T::from_str(c).unwrap())
        .collect()
}

#[allow(dead_code)]
fn read_as_string() -> String {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).unwrap();
    s.trim().to_string()
}

fn calc_size(table: &Vec<Vec<char>>, cur: (usize, usize), visited: &mut Vec<Vec<bool>>) -> usize {
    let mut queue: VecDeque<(usize, usize)> = VecDeque::new();
    let (mut whilte, mut black) = (0, 0);
    queue.push_back(cur);

    while let Some(cur) = queue.pop_front() {
        if visited[cur.0][cur.1] {
            continue;
        }
        visited[cur.0][cur.1] = true;
        if table[cur.0][cur.1] == '#' {
            whilte += 1;
        } else {
            black += 1;
        }

        if cur.0 > 0 {
            if table[cur.0 - 1][cur.1] != table[cur.0][cur.1] && !visited[cur.0 - 1][cur.1] {
                queue.push_back((cur.0 - 1, cur.1));
            }
        }

        if cur.0 < table.len() - 1 {
            if table[cur.0 + 1][cur.1] != table[cur.0][cur.1] && !visited[cur.0 + 1][cur.1] {
                queue.push_back((cur.0 + 1, cur.1));
            }
        }

        if cur.1 > 0 {
            if table[cur.0][cur.1 - 1] != table[cur.0][cur.1] && !visited[cur.0][cur.1 - 1] {
                queue.push_back((cur.0, cur.1 - 1));
            }
        }

        if cur.1 < table[0].len() - 1 {
            if table[cur.0][cur.1 + 1] != table[cur.0][cur.1] && !visited[cur.0][cur.1 + 1] {
                queue.push_back((cur.0, cur.1 + 1));
            }
        }
    }

    return whilte * black;
}

fn main() {
    let line = read_as_vec::<usize>();
    let (h, w) = (line[0], line[1]);
    let mut table: Vec<Vec<char>> = vec![];
    for _ in 0..h {
        table.push(read_as_string().chars().collect::<Vec<char>>());
    }
    let mut visited: Vec<Vec<bool>> = vec![vec![false; w]; h];
    let mut count: usize = 0;
    for i in 0..h {
        for j in 0..w {
            if !visited[i][j] {
                count += calc_size(&table, (i, j), &mut visited);
            }
        }
    }

    println!("{}", count);
}