import qualified Data.Map.Strict as M
import Data.Array
import Data.STRef
import Control.Monad
import Control.Monad.ST

{-
地図、スタート座標が与えられる。
スタート座標はすでに消されている。
-}
connected_part::Array (Int,Int) Char->(Int,Int)->STRef s (M.Map (Int,Int) ())->ST s (Int,Int)
connected_part ar (i,j) ref = do
                              let (_,(h,w)) = bounds ar
                              let nexts' = next h w (i,j)
                              m<-readSTRef ref
                              let nexts  = filter (\ c -> M.member c m) nexts'
                              if ar!(i,j)=='#' then do
                                                    let able = filter (\c -> ar!c == '.') nexts
                                                    forM_ able (\ c -> do
                                                                      m<-readSTRef ref
                                                                      writeSTRef ref (M.delete c m))
                                                    ls <- forM able (\c -> connected_part ar c ref)
                                                    return ((sum (map fst ls)),1+(sum (map snd ls)))
                                               else do
                                                    let able = filter (\c -> ar!c == '#') nexts
                                                    forM_ able (\ c -> do
                                                                      m<-readSTRef ref
                                                                      writeSTRef ref (M.delete c m))
                                                    ls <- forM able (\c -> connected_part ar c ref)
                                                    return (1+(sum (map fst ls)),(sum (map snd ls)))

loop::Array (Int,Int) Char->STRef s (M.Map (Int,Int) ())->ST s [(Int,Int)]
loop ar ref = do
              m<-readSTRef ref
              if m == M.empty then return []
                              else do
                                    let ((i,j),_) = M.findMin m
                                    writeSTRef ref (M.delete (i,j) m)
                                    d<-connected_part ar (i,j) ref
                                    rest<-loop ar ref
                                    return (d:rest)

next::Int->Int->(Int,Int)->[(Int,Int)]
next h w (i,j) = filter (\(a,b)-> a>0 && a<=h && b>0 && b<=w) [(i+1,j),(i-1,j),(i,j+1),(i,j-1)]


solver::Array (Int,Int) Char -> Int
solver ar = runST $ do
                    let (_,(h,w)) = bounds ar
                    ref<-newSTRef (M.fromList [((i,j),())|i<-[1..h],j<-[1..w]])
                    dat<-loop ar ref
                    return (sum (map (\(x,y)->x*y) dat))


main::IO()
main=do
  (h:w:_)<-return.(map read).words=<<getLine
  dat<-forM [1..h] (\_ -> getLine)
  print (solver (listArray ((1,1),(h,w)) (concat dat)))
