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 C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Diagnostics;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
using static Reader;
using static System.Math;

class P
{
    static void Main()
    {
        int[] hw = Console.ReadLine().Split().Select(int.Parse).ToArray();
        int h = hw[0];
        int w = hw[1];
        string[] map = Enumerable.Repeat(0, h).Select(_ => Console.ReadLine()).ToArray();
        UnionFind uf = new UnionFind(h * w);
        for (int i = 0; i < h; i++)
        {
            for (int j = 0; j < w - 1; j++)
            {
                if (map[i][j] != map[i][j + 1]) uf.Unite(i * w + j, i * w + j + 1);
            }
        }
        for (int i = 0; i < h - 1; i++)
        {
            for (int j = 0; j < w; j++)
            {
                if (map[i][j] != map[i + 1][j]) uf.Unite(i * w + j, (i + 1) * w + j);
            }
        }

        var groups = uf.GetGroupes;
        int res = 0;
        foreach (var group in groups)
        {
            var c1 = 0;
            var c2 = 0;
            foreach (var elem in group)
            {
                
                int bh = elem / w;
                int bw = elem % w;
                if ((bh % 2 + bw % 2) % 2 == 0) c1++;
                else c2++;
            }
            c1.WriteLog();
            c2.WriteLog();
            res += c1 * c2;
        }
        res.WriteLine();
    }
}


class UnionFind
{
    int[] data;
    public UnionFind(int count)
    {
        data = Enumerable.Range(0, count).ToArray();
    }
    public void Unite(int x, int y)
    {
        int xp = Parent(x);
        int yp = Parent(y);
        if (xp != yp)
        {
            data[yp] = xp;
        }
    }
    public bool IsSameGroup(int x, int y) => Parent(x) == Parent(y);
    public int[] AllParents() => data.Where((x, y) => x == y).ToArray();
    public IEnumerable<IEnumerable<int>> GetGroupes => data.Select((x, y) => new Tuple<int, int>(Parent(x), y)).GroupBy(x => x.Item1).Select(x => x.Select(y => y.Item2));
    public int Parent(int x)
    {
        form(x);
        return data[x];
    }
    private void form(int x)
    {
        while (data[x] != data[data[x]])
        {
            data[x] = data[data[x]];
        }
    }
}

#region io
static class Reader
{
    static TextReader stdinReader = Console.In;

    public static char NextChar => (char)stdinReader.Read();
    public static int NextInt => ReadInt();
    public static long NextLong => ReadLong();
    public static string NextString => ReadString();
    public static IEnumerable<int> NextIntCollection => ReadIntCollection();
    public static IEnumerable<long> NextLongCollection => ReadLongCollection();
    public static IEnumerable<string> NextStringCollection => ReadStringCollection();
    public static string NextLine => stdinReader.ReadLine();

    public static int ReadInt()
    {
        int i;
        bool isNegative;
        checked
        {
            i = 0;
            isNegative = false;
            char next = NextChar;
            while (char.IsWhiteSpace(next)) next = NextChar;
            while (true)
            {
                if (!char.IsDigit(next))
                {
                    if (next == '-')
                    {
                        isNegative = true;
                    }
                    else if (next != '+') break;
                }
                else
                {
                    i *= 10;
                    i += next - '0';
                }
                next = NextChar;
            }
        }
        return isNegative ? -i : i;
    }

    public static long ReadLong()
    {
        long i;
        bool isNegative;
        checked
        {
            i = 0;
            isNegative = false;
            char next = NextChar;
            while (char.IsWhiteSpace(next)) next = NextChar;
            while (true)
            {
                if (!char.IsDigit(next))
                {
                    if (next == '-')
                    {
                        isNegative = true;
                    }
                    else if (next != '+') break;
                }
                else
                {
                    i *= 10;
                    i += next - '0';
                }
                next = NextChar;
            }
        }
        return isNegative ? -i : i;
    }

    public static string ReadString()
    {
        StringBuilder builder = new StringBuilder();
        char next = NextChar;
        while (char.IsWhiteSpace(next)) next = NextChar;
        while (true)
        {
            if (char.IsWhiteSpace(next)) break;
            builder.Append(next);
            next = NextChar;
        }
        return builder.ToString();
    }

    public static IEnumerable<int> ReadIntCollection()
    {
        int i;
        bool isNegative;
        char next;
        while (true)
        {
            i = 0;
            isNegative = false;
            next = NextChar;
            while (char.IsWhiteSpace(next)) next = NextChar;
            while (true)
            {
                if (!char.IsDigit(next))
                {
                    if (next == '-')
                    {
                        isNegative = true;
                    }
                    else if (next != '+') break;
                }
                else
                {
                    i *= 10;
                    i += next - '0';
                }
                next = NextChar;
            }
            yield return isNegative ? -i : i;
            if (!char.IsSeparator(next)) break;
        }
    }

    public static IEnumerable<long> ReadLongCollection()
    {
        long i;
        bool isNegative;
        char next;
        while (true)
        {
            i = 0;
            isNegative = false;
            next = NextChar;
            while (char.IsWhiteSpace(next)) next = NextChar;
            while (true)
            {
                if (!char.IsDigit(next))
                {
                    if (next == '-')
                    {
                        isNegative = true;
                    }
                    else if (next != '+') break;
                }
                else
                {
                    i *= 10;
                    i += next - '0';
                }
                next = NextChar;
            }
            yield return isNegative ? -i : i;
            if (!char.IsSeparator(next)) break;
        }
    }

    public static IEnumerable<string> ReadStringCollection()
    {
        StringBuilder builder = new StringBuilder();
        char next;
        while (true)
        {
            builder.Clear();
            next = NextChar;
            while (char.IsWhiteSpace(next)) next = NextChar;
            while (true)
            {
                if (char.IsWhiteSpace(next)) break;
                builder.Append(next);
                next = NextChar;
            }
            yield return builder.ToString();
            if (!char.IsSeparator(next)) break;
        }
    }
}

static class Writer
{
    public static void WriteLine<T>(this T item) => Console.WriteLine(item);

    public static void WriteLog<T>(this T item) => Debug.WriteLine(item);
}
#endregion

#region arrayoperation
static class ArrayOperation
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static IEnumerable<int> Compress<T>(this IEnumerable<T> enumerable) where T : IComparable<T>
    {
        var dict = enumerable.OrderBy(x => x).Distinct().Select((x, y) => new Tuple<T, int>(x, y)).ToDictionary(x => x.Item1, x => x.Item2);
        return enumerable.Select(x => dict[x]);
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool Exists<T>(this IEnumerable<T> enumerable, Func<T, bool> selector)
    {
        foreach (var item in enumerable) if (selector(item)) return true;
        return false;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
    {
        foreach (var item in enumerable) action(item);
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static T1 MinElement<T1, T2>(this IEnumerable<T1> enumerable, Func<T1, T2> selector) where T2 : IComparable<T2>
    {
        T1 minElem = default(T1);
        T2 min = default(T2);
        bool isFirst = true;
        foreach (var item in enumerable)
        {
            var next = selector(item);
            if (min.CompareTo(next) > 0 || isFirst)
            {
                isFirst = false;
                minElem = item;
                min = next;
            }
        }
        return minElem;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static T1 MaxElement<T1, T2>(this IEnumerable<T1> enumerable, Func<T1, T2> selector) where T2 : IComparable<T2>
    {
        T1 maxElem = default(T1);
        T2 max = default(T2);
        bool isFirst = true;
        foreach (var item in enumerable)
        {
            var next = selector(item);
            if (max.CompareTo(next) < 0 || isFirst)
            {
                isFirst = false;
                maxElem = item;
                max = next;
            }
        }
        return maxElem;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static int MinIndex<T1, T2>(this IEnumerable<T1> enumerable, Func<T1, T2> selector) where T2 : IComparable<T2>
    {
        int currentInd = 0;
        int maxInd = 0;
        T2 max = default(T2);
        bool isFirst = true;
        foreach (var item in enumerable)
        {
            var next = selector(item);
            if (max.CompareTo(next) > 0 || isFirst)
            {
                isFirst = false;
                max = next;
                maxInd = currentInd;
            }
            currentInd++;
        }
        return maxInd;
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static int MaxIndex<T1, T2>(this IEnumerable<T1> enumerable, Func<T1, T2> selector) where T2 : IComparable<T2>
    {
        int currentInd = 0;
        int maxInd = 0;
        T2 max = default(T2);
        bool isFirst = true;
        foreach (var item in enumerable)
        {
            var next = selector(item);
            if (max.CompareTo(next) < 0 || isFirst)
            {
                isFirst = false;
                max = next;
                maxInd = currentInd;
            }
            currentInd++;
        }
        return maxInd;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> enumerable) => enumerable.OrderBy(_ => RNG.NextULong());
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static string ToString<T>(this IEnumerable<T> enumerable, string separator = " ") => string.Join(separator, enumerable);
}
#endregion

#region utils
static class RNG
{
    private static ulong _xorshift_x = (ulong)DateTime.Now.Ticks * 0x3141592c0ffee;
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool NextBool() => (NextULong() & 1) == 1;
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static sbyte NextSByte()
    {
        unchecked
        {
            return (sbyte)NextULong();
        }
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static sbyte NextSByte(sbyte MinValue, sbyte MaxValue) => (sbyte)(NextSByte() % (MaxValue - MinValue) + MinValue);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static byte NextByte()
    {
        unchecked
        {
            return (byte)NextULong();
        }
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static byte NextByte(byte MinValue, byte MaxValue) => (byte)(NextByte() % (MaxValue - MinValue) + MinValue);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static short NextShort()
    {
        unchecked
        {
            return (short)NextULong();
        }
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static short NextShort(short MinValue, short MaxValue) => (short)(NextShort() % (MaxValue - MinValue) + MinValue);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static ushort NextUShort()
    {
        unchecked
        {
            return (ushort)NextULong();
        }
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static ushort NextUShort(ushort MinValue, ushort MaxValue) => (ushort)(NextUShort() % (MaxValue - MinValue) + MinValue);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static int NextInt()
    {
        unchecked
        {
            return (int)NextULong();
        }
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static int NextInt(int MinValue, int MaxValue) => NextInt() % (MaxValue - MinValue) + MinValue;
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static uint NextUInt()
    {
        unchecked
        {
            return (uint)NextULong();
        }
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static uint NextUInt(uint MinValue, uint MaxValue) => NextUInt() % (MaxValue - MinValue) + MinValue;
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static long NextLong()
    {
        unchecked
        {
            return (long)NextULong();
        }
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static long NextLong(long MinValue, long MaxValue) => NextLong() % (MaxValue - MinValue) + MinValue;
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static ulong NextULong()
    {
        _xorshift_x = _xorshift_x ^ (_xorshift_x << 7);
        _xorshift_x = _xorshift_x ^ (_xorshift_x >> 9);
        return _xorshift_x;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static ulong NextULong(ulong MinValue, ulong MaxValue) => NextULong() % (MaxValue - MinValue) + MinValue;
}
#endregion