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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.util.StringTokenizer;


class Main{
	static int[][] ban;
	static boolean[][] visited;
	static long sum=0;
	static int H,W;
	static long kuro=0;
	static long siro=0;
	public static void main(String[] args) {
		SC sc=new SC(System.in);
		H=sc.nextInt();
		W=sc.nextInt();
		visited=new boolean[H][W];
		ban=new int[H][W];
		String s;
		for(int i=0; i<H; i++){
			s=sc.next();
			for(int j=0; j<W; j++){
				if(s.charAt(j)=='#'){
					ban[i][j]=1;	//黒
				}
				else{
					ban[i][j]=0;	//白
				}
			}
		}

		for(int i=0; i<H; i++){		//しらべる
			for(int j=0; j<W; j++){
				if(ban[i][j]==1 && !visited[i][j]){
					kuro=0; siro=0;
					dfs(i,j);
					sum+=kuro*siro;
				}
			}
		}
		pl(sum);
	}

	public static void dfs(int y,int x){
		int[] vx={0,1,0,-1};
		int[] vy={-1,0,1,0};
		if(ban[y][x]==1){
			kuro++;
		}
		else{
			siro++;
		}
		visited[y][x]=true;
		for(int i=0; i<4; i++){
			if(x+vx[i]>=0 && x+vx[i]<W && y+vy[i]>=0 && y+vy[i]<H){
				if(ban[y][x]!=ban[y+vy[i]][x+vx[i]] && !visited[y+vy[i]][x+vx[i]]){
					dfs(y+vy[i],x+vx[i]);
				}
			}
		}
	}
	public static void pl(Object o) {
		System.out.println(o);
	}
	public static void pl() {
		System.out.println();
	}
	public static void p(Object o) {
		System.out.print(o);
	}
	static class SC {
		private BufferedReader reader = null;
		private StringTokenizer tokenizer = null;
		public SC(InputStream in) {
			reader = new BufferedReader(new InputStreamReader(in));
		}
		public String next() {
			if (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					tokenizer = new StringTokenizer(reader.readLine());
				} catch (IOException e) {
					throw new UncheckedIOException(e);
				}
			}
			return tokenizer.nextToken();
		}
		public int nextInt() {
			return Integer.parseInt(next());
		}
		public long nextLong() {
			return Long.parseLong(next());
		}
		public double nextDouble() {
			return Double.parseDouble(next());
		}
		public String nextLine() {
			try {
				return reader.readLine();
			} catch (IOException e) {
				throw new UncheckedIOException(e);
			}
		}
	}
}