module UnionFind_i32 = struct
  let init n = Array.make n (-1)
  let is_root i a = a.(i) < 0
  let rec root_destructive x a =
    if a.(x) < 0 then x
    else (a.(x) <- root_destructive a.(x) a; a.(x))
  let size_destructive i a = let r = root_destructive i a in -r
  let same_destructive x y a = root_destructive x a = root_destructive y a
  let connect_destructive x y a =
    let p,q = root_destructive x a,root_destructive y a
    in if p = q then () else (
      let p,q = if a.(p) > a.(q) then q,p else p,q
      in
      a.(p) <- a.(p) + a.(q); a.(q) <- p)
end;;
Scanf.(Array.(scanf " %d %d" @@ fun h w ->
  let m = init h (fun _ -> scanf " %s" @@ fun v -> v) in
  let enc i j = i*w+j in
  UnionFind_i32.(
    let uf = init (h*w) in
    let k0,k1 = make (h*w) 0,make (h*w) 0 in
    iteri (fun i -> String.iteri (fun j c ->
      (if c='#' then k0 else k1).(enc i j) <- 1)) m;
    iteri (fun i ->
      String.iteri (fun j _ ->
        for k=0 to 1 do
          let s,t = i+k,j+1-k in
          if
            0<=s && s<=h-1 &&
            0<=t && t<=w-1 &&
            m.(s).[t] <> m.(i).[j] &&
            not @@ same_destructive (enc i j) (enc s t) uf
          then (
            (* Printf.printf " %d %d (%d) -- %d %d (%d)\n" i j (enc i j) s t (enc s t) ; *)
            let u,v =
              root_destructive (enc i j) uf,
              root_destructive (enc s t) uf in
            let w = k0.(u) in
            k0.(u) <- k0.(u) + k0.(v);
            k0.(v) <- k0.(v) + w;
            let w = k1.(u) in
            k1.(u) <- k1.(u) + k1.(v);
            k1.(v) <- k1.(v) + w;
            connect_destructive (enc i j) (enc s t) uf
          )
        done;
      )
    ) m;
    fold_left (fun (sum,i) _ ->
      if is_root i uf then (
        let u,v = k0.(i),k1.(i) in
        (sum + u*v, i+1)
      ) else (sum, i+1)
    ) (0,0) uf
    |> fst |> print_int)))