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: Wrong Answer)

import java.util.*;

public class Main {
    static final int MOD = 1000000007;
	public static void main (String[] args) {
		Scanner sc = new Scanner(System.in);
		int h = sc.nextInt();
		int w = sc.nextInt();
		UnionFindTree uft = new UnionFindTree(h, w);
		char[][] field = new char[h][];
		for (int i = 0; i < h; i++) {
		    field[i] = sc.next().toCharArray();
		    for (int j = 0; j < w; j++) {
		        if (field[i][j] == '#') {
		            uft.setBlack(i, j);
		        } else {
		            uft.setWhite(i, j);
		        }
		    }
		}
		
		for (int i = 0; i < h; i++) {
		    for (int j = 0; j < w; j++) {
		        if (field[i][j] == '.') {
		            continue;
		        }
		        if (i != 0 && field[i - 1][j] == '.') {
		            uft.unite(i, j, i - 1, j);
		        }
		        if (i != h - 1 && field[i + 1][j] == '.') {
		            uft.unite(i, j, i + 1, j);
		        }
		        if (j != 0 && field[i][j - 1] == '.') {
		            uft.unite(i, j, i, j - 1);
		        }
		        if (j != w - 1 && field[i][j + 1] == '.') {
		            uft.unite(i, j, i, j + 1);
		        }
		        
		    }
		}
	    System.out.println(uft.getCount());
	}
	
	static class UnionFindTree {
	    int h;
	    int w;
	    int[] parents;
	    int[] blacks;
	    int[] whites;
	    
	    public UnionFindTree(int h, int w) {
	        this.h = h;
	        this.w = w;
	        int size = h * w;
	        parents = new int[size];
	        blacks = new int[size];
	        whites = new int[size];
	        for (int i = 0; i < size; i++) {
	            parents[i] = i;
	        }
	    }
	    
	    public int find (int x) {
	        if (parents[x] == x) {
	            return x;
	        } else {
	            return parents[x] = find(parents[x]);
	        }
	    }
	    
	    public void unite(int h1, int w1, int h2, int w2) {
	        unite(h1 * w + w1, h2 * w + w2);
	    }
	    
	    public void unite(int x, int y) {
	        int xx = find(x);
	        int yy = find(y);
	        if (xx == yy) {
	            return;
	        }
	        parents[xx] = yy;
	        blacks[yy] += blacks[xx];
	        whites[yy] += whites[xx];
	    }
	    
	    public void setBlack(int h1, int w1) {
	        blacks[h1 * w + w1]++;
	    }
	    
	    public void setWhite(int h1, int w1) {
	        whites[h1 * w + w1]++;
	    }
	    
	    public long getCount() {
	        long total = 0;
	        for (int i = 0; i < parents.length; i++) {
	            if (parents[i] == i) {
	                total += blacks[i] * whites[i];
	            }
	        }
	        return total;
	    }
	}
}