import qualified Data.Text as T
import qualified Data.Text.IO as T
import qualified Data.Text.Read as T
import qualified Data.Vector.Unboxed as V
import qualified Data.IntSet as S
import Data.Bool (bool)

main :: IO ()
main = do
  (h : w : _) <- map unsafeSignedDecimal . T.words <$> T.getLine :: IO [Int]
  let
    encode :: (Int, Int) -> Int
    encode (i, j) = i + h + j
    decode :: Int -> (Int, Int)
    decode n = divMod n h
    shiftU :: Int -> Maybe Int
    shiftU n = let {(i, j) = decode n; i' = pred i} in bool Nothing (Just . encode $ (i', j)) (i' >= 0)
    shiftD :: Int -> Maybe Int
    shiftD n = let {(i, j) = decode n; i' = succ i} in bool Nothing (Just . encode $ (i', j)) (i' < h)
    shiftL :: Int -> Maybe Int
    shiftL n = let {(i, j) = decode n; j' = pred j} in bool Nothing (Just . encode $ (i, j')) (j' >= 0)
    shiftR :: Int -> Maybe Int
    shiftR n = let {(i, j) = decode n; j' = succ j} in bool Nothing (Just . encode $ (i, j')) (j' < w)
    candidates :: Int -> [Int]
    candidates n = [shiftU n, shiftD n, shift L n, shift R n] >>= maybe [] pure
  as <- V.fromList . concat . map (T.foldr ((:) . (== '#')) []) . T.lines <$> T.getContents :: V.Vector Bool
  let
    bijs = filter (as V.!) $ [0..(pred (h * w))] :: [Int]
    n = search 0 bijs (S.fromAscendingList . bijs) :: Int
    search :: Int -> [Int] -> S.IntSet -> Int
    search k [] _ = k
    search k targets blacks = search (succ k) targets' blacks'
      where
        (targets', blacks') =  foldr step ([], blacks) . concat . map candidates $ targets
  print n

step :: Int -> ([Int], S.IntSet) -> ([Int], S.IntSet)
step t (ts, bs) = if S.member t bs then (ts, bs) else (t : ts, S.insert t bs)

unsafeSignedDecimal :: T.Text -> Int
unsafeSignedDecimal s = case T.signed T.decimal s of
  Right (n, _) -> n
