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 Java8 (OpenJDK 1.8.0) (judge verdict: Accepted)

import java.awt.Point;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
 
public class Main {
	static char[][] c;
	static int H, W;
	static List<Point> p;
	static long ans = 0;
	static boolean[][] m;
	static int[][] g;
	static long cnt1 = 0;
	static long cnt2 = 0;
	static int[][] h;
	static Set<Integer> set1;
	static Set<Integer> set2;
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		H = sc.nextInt();
		W = sc.nextInt();
		String[] S = new String[H];
		for(int i = 0; i < H; i++) {
			S[i] = sc.next();
		}
		sc.close();
		c = new char[H][W];
		m = new boolean[H][W];
		g = new int[H][W];
		h = new int[H][W];
		set1 = new HashSet<Integer>();
		set2 = new HashSet<Integer>();
		for(int i = 0; i < H; i++) {
			for(int j = 0; j < W; j++) {
				m[i][j] = true;
			}
		}
		p = new ArrayList<Point>();
		for(int i = 0; i < H; i++) {
			for(int j = 0; j < W; j++) {
				c[i][j] = S[i].charAt(j);
				if(c[i][j] == '#') {
					p.add(new Point(j, i));
				}
			}
		}
		for(int i = 0; i < p.size(); i++) {
			int x = p.get(i).x;
			int y = p.get(i).y;
			//System.out.println(y + " " + x);
			if(g[y][x] == 1) {
				continue;
			}
			g[y][x] = 1;
			h[y][x] = 1;
			m[y][x] = false;
			rec('#', x, y);
			m[y][x] = true;
			int k = (y + 1) * H + x + 1;
			set2.add(k);
			cnt1 = set1.size();
			cnt2 = set2.size();
 
			//System.out.println(cnt1 +" " + cnt2);
			ans += cnt1 * cnt2;
			set1.clear();
			set2.clear();
		}
		System.out.println(ans);
	}
	static void init() {
		for(int i = 0; i < H; i++) {
			for(int j = 0; j < W; j++) {
				h[i][j] = 0;
			}
		}
	}
	static void rec(char color, int x, int y) {
		int[] dx = {1, -1, 0, 0};
		int[] dy = {0, 0, 1, -1};
		for(int i = 0; i < 4; i++) {
			int nx = x + dx[i];
			int ny = y + dy[i];
			if(nx >= 0 && nx < W && ny >= 0 && ny < H) {
				if(color == '#' && m[ny][nx] && c[ny][nx] == '.') {
					m[ny][nx] = false;
					rec('.', nx, ny);
					//m[ny][nx] = true;
					int k = (ny + 1) * H + nx + 1;
					set1.add(k);
					//h[ny][nx] = 1;
				}else if(color == '.' && m[ny][nx] && c[ny][nx] == '#') {
					g[ny][nx] = 1;
					m[ny][nx] = false;
					rec('#', nx, ny);
					//m[ny][nx] = true;
					g[ny][nx] = 1;
					int k = (ny + 1) * H + nx + 1;
					set2.add(k);
					//h[ny][nx] = 1;
				}
			}
		}
	}
}