Problem: 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.

Examples

Input

3 3
.#.
..#
#..


Output

10


Input

3 3
.#.
..#
..


Output

10


Input

2 4
....
....


Output

0


Input

4 3


...


Output

6

Solution (in JAVA):

Solution:
import java.util.Arrays;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int H = sc.nextInt();
        int W = sc.nextInt();
        char[][] grid = new char[H][W];
        for(int i = 0; i < H; i++) grid[i] = sc.next().toCharArray();
        sc.close();
        DJSet ds = new DJSet(H*W);
        for(int i = 0; i < H; i++){
            for(int j = 0; j < W; j++){
                if(i+1 < H && grid[i][j] != grid[i+1][j]){
                    ds.union(i*W +j, (i+1)*W +j);
                }
                if(j+1 < W && grid[i][j] != grid[i][j+1]){
                    ds.union(i*W +j, i*W +j +1);
                }
            }
        }
        int[] b = new int[H*W];
        int[] w = new int[H*W];
        for(int i = 0; i < H; i++){
            for(int j = 0; j < W; j++){
                if(grid[i][j] == '.') w[ds.root(i*W +j)]++;
                else b[ds.root(i*W +j)]++;
            }
        }
        long ans = 0;
        for(int i = 0; i < H*W; i++){
            ans += (long)b[i]*w[i];
        }
        System.out.println(ans);
    }

}

class DJSet {
    public int[] upper;

    public DJSet(int n){
        upper = new int[n];
        Arrays.fill(upper, -1);
    }

    /*
     * 要素xが含まれる集合のrootを求める.
     * rootを求める過程で経路圧縮しrootが親になるようにする.
     */
    public int root(int x){
        return upper[x] < 0 ? x : (upper[x] = root(upper[x]));
    }

    /*
     * 要素xと要素yが同じ集合か判定する.
     */
    public boolean same(int x, int y){
        return root(x) == root(y);
    }

    /*
     * 要素xと要素yを含むそれぞれの集合を合併する.
     * 要素数の多い集合のrootを残し、少ないほうのrootをその下に合併する.
     */
    public boolean union(int x, int y){
        x = root(x);
        y = root(y);
        if(x != y){
            if(upper[y] < upper[x]){
                int t = x;
                x = y;
                y = t;
            }
            upper[x] += upper[y];
            upper[y] = x;
        }
        return x == y;
    }

    /*
     * 集合の数を数える.
     */
    public int count(){
        int c = 0;
        for(int u :upper){
            if(u < 0) c++;
        }
        return c;
    }
}