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)

use std::io;
//use std::collections::HashMap;
//use std::collections::BinaryHeap;
//use std::collections::HashSet;
//use std::mem; // mem::swap(&mut x,&mut y);
use std::cmp; // cmp::max,cmp::min

// Rust memo: https://hackmd.io/i0lQY1OKTDW1t66TECOmiw?both

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

#[allow(dead_code)]
fn read_charvec() -> Vec<char>{
    read_line().chars().collect()
}

#[allow(dead_code)]
fn read_ints() -> Vec<i64>{
    let s = read_line();
    let split:Vec<&str> = s.split(" ").collect();
    split.iter().map(|&x| x.to_string().parse().unwrap()).collect()
}

#[allow(dead_code)]
fn read_int() -> i64{
    read_ints()[0]
}

#[allow(dead_code)]
fn reverse(s: &String) -> String{
    s.chars().rev().collect::<String>()
}

#[allow(dead_code)]
fn read_lines(n:i64) -> Vec<String>{
    let mut xs = Vec::new();

    for _i in 0..n{
        xs.push(read_line());
    }

    xs
}

#[allow(dead_code)]
fn read_ints2(n:i64) -> Vec<i64>{
    read_lines(n).iter().map(|x| x.parse().unwrap()).collect()
}

#[allow(dead_code)]
fn arange(start:i64,end:i64,step:i64) -> Vec<i64>{
    let mut ret = Vec::new();
    let mut i = start;

    while i < end{
        ret.push(i);
        i += step;
    }

    ret
}

#[allow(dead_code)]
const DXS : [i64; 4] = [0,0,1,-1];
#[allow(dead_code)]
const DYS : [i64; 4]  = [1,-1,0,0];
#[allow(dead_code)]
const INF : i64 = 999999999;
#[allow(dead_code)]
const N_PRIME : i64 = 1000000007;

////////////////////////////////////////////////

fn get_color(board:&Vec<Vec<bool>>) -> i64{
    let mut result = vec![vec![0;board[0].len()];board.len()];
    let mut ans = 0;

    for i in 0..board.len(){
        for j in 0..board[0].len(){
            let c = i*board[0].len() + j+1;
            let (b,w) = fill(i,j,&mut result,board,c as i64,board[i][j]);
            let pattern = b*w;
            ans += pattern;
        }
    }

    ans
}

fn fill(x:usize,y:usize,result:&mut Vec<Vec<i64>>,board:&Vec<Vec<bool>>,c:i64,wait:bool)->(i64,i64){
    let mut b = 0;
    let mut w = 0;

    if result[x][y] == 0{
        if board[x][y] != wait{
            return (0,0);
        }

        result[x][y] = c;

        for i in 0..4{
            let dx = DXS[i];
            let dy = DYS[i];
            let xx = x as i64 + dx;
            let yy = y as i64 + dy;

            if xx < 0 || xx >= board.len() as i64 || yy < 0 || yy >= board[0].len() as i64{
                continue;
            }
            let (bb,ww) = fill(xx as usize,yy as usize,result,board,c,!wait);

            b += bb;
            w += ww;
        }

        if board[x][y]{
            (b+1,w)
        }else{
            (b,w+1)
        }
    }else{
        (0,0)
    }
}

fn main(){
    let inputs = read_ints();
    let h = inputs[0] as usize;
    let mut board : Vec<Vec<bool>> = vec![];

    for _ in 0..h{
        board.push(
            read_line()
            .chars()
            .map(|x| x == '#')
            .collect()
        );
    }

    let colors = get_color(&board);
    println!("{:?}",colors);
}