{-# LANGUAGE BangPatterns #-}
import Control.Arrow
import Control.Monad.Fix
import Data.Foldable
import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VM
import qualified Data.ByteString.Char8 as B
import System.IO.Unsafe
import Data.Graph
import Debug.Trace

solve :: Int -> Int -> V.Vector B.ByteString -> Int
solve h w ss = dfs
  where
    dfs :: Int
    dfs = snd $ (\f -> foldl' f (unsafePerformIO (VM.replicate (w*h) False), 0) [0..w*h-1]) $ \(!check,!acc) i ->
      if unsafePerformIO (VM.read check i)
        then (check,acc)
        else let acc' = ((\(x,y) -> x*y + acc) $ search check (toIndex i)) in (check,acc')

    search :: VM.IOVector Bool -> (Int,Int) -> (Int,Int)
    search check = fix (\f (!check,!bw,!i) ->
      if unsafePerformIO (VM.read check (fromIndex i))
        then bw
        else 
          let bw' = (if ss !+ i == '#' then first (+1) else second (+1)) bw in
          let ns = VU.fromList $ neighbors check i in
            ns `seq` unsafePerformIO (VM.write check (fromIndex i) True) `seq`
            VU.foldl' (\bw'' i' -> f (check,bw'',i')) bw' ns
      ) . (,,) check (0,0)

    toIndex :: Int -> (Int,Int)
    toIndex n = (n `mod` w, n `div` w)

    fromIndex :: (Int,Int) -> Int
    fromIndex (x,y) = y * w + x

    (!+) :: V.Vector B.ByteString -> (Int,Int) -> Char
    vec !+ (x,y) = (vec V.! y) `B.index` x

    neighbors check (x,y) =
      [(x',y') |
        (ix,iy) <- [(0,1),(0,-1),(1,0),(-1,0)],
        let x' = x + ix, let y' = y + iy,
        0 <= x' && x' < w, 0 <= y' && y' < h,
        ss !+ (x',y') /= ss !+ (x,y),
        not (unsafePerformIO (VM.read check (fromIndex (x,y))))
      ]

main = do
  let readInt = fmap (second B.tail) . B.readInt

  hw <- V.unfoldrN 2 readInt <$> B.getLine
  ss <- V.replicateM (hw V.! 0) B.getLine
  print $ solve (hw V.! 0) (hw V.! 1) ss
