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.*;
import java.io.*;

public class Main {

  private static void solve() {
    int h = nextInt();
    int w = nextInt();

    char[][] g = new char[h][w];

    for (int i = 0; i < h; i++) {
      g[i] = next().toCharArray();
    }

    boolean[][] visit = new boolean[h][w];

    long ans = 0;
    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        if (g[i][j] == '#' && !visit[i][j]) {
          ans += bfs(i, j, visit, g, h, w);
        }
      }
    }

    System.out.println(ans);
  }

  private static long bfs(int i, int j, boolean[][] visit, char[][] g, int h, int w) {
    int[] dx = {1, -1, 0, 0};
    int[] dy = {0, 0, 1, -1};
    Queue<int[]> queue = new LinkedList<>();
    queue.offer(new int[] {i, j, 0});
    visit[i][j] = true;

    long black = 1;
    long white = 0;
    while (!queue.isEmpty()) {
      int[] first = queue.poll();

      for (int k = 0; k < dx.length; k++) {
        int nx = first[0] + dx[k];
        int ny = first[1] + dy[k];

        int expected = (first[2] == 0 ? 1 : 0);
        char expectedChar = '#';
        if (expected == 1) {
          expectedChar = '.';
        }

        if (nx >= 0 && nx < h && ny >= 0 && ny < w && expectedChar == g[nx][ny] && !visit[nx][ny]) {
          visit[nx][ny] = true;
          if (g[nx][ny] == '#') {
            black++;
          } else {
            white++;
          }
          queue.offer(new int[] {nx, ny, expected});
        }
      }
    }
    return black * white;
  }

  private static void run() {
    br = new BufferedReader(new InputStreamReader(System.in));
    out = new PrintWriter(System.out);

    solve();

    out.close();
  }

  private static StringTokenizer st;
  private static BufferedReader br;
  private static PrintWriter out;

  private static String next() {
    while (st == null || !st.hasMoreElements()) {
      String s;
      try {
        s = br.readLine();
      } catch (IOException e) {
        return null;
      }
      st = new StringTokenizer(s);
    }
    return st.nextToken();
  }

  private static int nextInt() {
    return Integer.parseInt(next());
  }

  private static long nextLong() {
    return Long.parseLong(next());
  }

  public static void main(String[] args) {
    run();
  }
}