module DirectedGraph
  (* 道の表現 *)
  (Path : sig
    type t
    (* 辺の名前 *)
    type edge
    (* 長さ0の道 *)
    val nil : t
    (* 道の後ろに辺を付け足した道 *)
    val snoc : t -> edge -> t
  end) :
sig
  (* BFSにより，重みのないグラフの最短経路を求める *)
  val bfs :
    (* 頂点数（Hashtblを用いるので目安程度） *)
    int ->
    (* 辺の名前が付いた隣接リスト *)
    ('v -> ('v * Path.edge) list) ->
    (* 始点 *)
    'v ->
    (* 最短経路を返す関数 辿り着けなければNoneを返す） *)
    ('v -> Path.t option)
end = struct
  let rec bfs_aux es d frontier t =
    try Some (Hashtbl.find d t) with
    | Not_found ->
        match !frontier with
        | [] -> None
        | _ :: _ ->
            frontier := List.fold_right (fun u ->
              List.fold_right (fun (v, e) frontier ->
                if Hashtbl.mem d v
                then frontier
                else (Hashtbl.add d v (Path.snoc (Hashtbl.find d u) e); v :: frontier))
              (es u)) !frontier [];
            bfs_aux es d frontier t

  (*
   * 終点に辿り着いた時点で探索を切り上げるが，
   * 戻り値の関数を覚えておくと，途中まで探索した結果が再利用される
   * （#trace bfs_aux すると分かりやすい）
   *)
  let bfs n es s =
    let d = Hashtbl.create n in
    Hashtbl.add d s Path.nil;
    let frontier = ref [s] in
    bfs_aux es d frontier
end

module FlowNetwork
  (* 流量 *)
  (Flow : sig
    type t
    val inf : t
    val zero : t
    val ( + ) : t -> t -> t
    val ( - ) : t -> t -> t
    val compare : t -> t -> int
  end) :
sig
  val max_flow :
    (* 頂点の数（Hashtblを用いるので目安程度） *)
    int ->
    (* 各辺とその逆辺の容量 *)
    ('v * 'v * Flow.t * Flow.t) list ->
    (* 始点 *)
    'v ->
    (* 終点 *)
    'v ->
    (* 最大フロー *)
    Flow.t
end =
struct
  module G = DirectedGraph (struct
    type t = int
    type edge = unit
    let nil = 0
    let snoc t _ = t + 1
  end)

  (* 増加パスをDFSで探し，流せるだけ流していく *)
  let rec dfs capacity add_edge iter level v t f =
    if v = t then f
    else begin
      let rec find () =
        match Hashtbl.find iter v with
        | exception Not_found -> Flow.zero
        | (u, i) ->
            Hashtbl.remove iter v;
            (* capacity i <= 0 *)
            if Flow.compare (capacity i) Flow.zero <= 0 || level u <= level v then find ()
            else begin
              let d = dfs capacity add_edge iter level u t @@
                (* min f (capacity i) *)
                if Flow.compare f (capacity i) <= 0 then f else capacity i in
              (* d <= 0 *)
              if Flow.compare d Flow.zero <= 0 then find ()
              else (add_edge i d; d)
            end in find ()
    end

  let max_flow n es s t =
    assert (s <> t);
    (* 各辺に流せる流量 *)
    let capacity = Array.make (2 * List.length es) Flow.zero in
    (* 逆辺を張りつつ，隣接リスト形式に変換 *)
    let adj = Hashtbl.create n in
    List.iteri (fun i (u, v, c, c') ->
      (* 各辺は番号で管理する *)
      Hashtbl.add adj u (v, 2 * i);
      (* 容量はcapacityを見てほしい *)
      capacity.(2 * i) <- c;
      (* 逆辺 *)
      Hashtbl.add adj v (u, 2 * i + 1);
      capacity.(2 * i + 1) <- c') es;
    (* 番号iの辺にcだけフローを流す *)
    let add_edge i c =
      let open Flow in
      capacity.(i) <- capacity.(i) - c;
      (* 逆辺 *)
      capacity.(i lxor 1) <- capacity.(i lxor 1) + c in
    let rec outer flow =
      let level = G.bfs n (fun v ->
        List.concat @@ List.map (fun (u, i) ->
          if Flow.compare capacity.(i) Flow.zero <= 0 then []
          else [(u, ())]) @@ Hashtbl.find_all adj v) s in
      if level t = None then flow
      else
        let iter = Hashtbl.copy adj in
        let rec inner flow =
          let f = dfs (fun i -> capacity.(i)) add_edge iter level s t Flow.inf in
          if Flow.compare f Flow.zero <= 0 then flow
          else inner (Flow.( + ) flow f) in
        outer @@ inner flow in
    outer Flow.zero
end

module G = FlowNetwork (struct
  include Pervasives
  type t = int
  let zero = 0
  let inf = max_int
end)

let () = Scanf.scanf "%d %d\n" @@ fun h w ->
  let ass = Array.init h @@ fun _ -> Scanf.scanf "%s\n" @@ fun s -> s in
  let yxs =
    List.concat @@ Array.to_list @@ Array.init h @@ fun y ->
      Array.to_list @@ Array.init w @@ fun x -> y, x in
  let [(sy, sx); (ty, tx)] =
    List.map (fun c ->
      List.find (fun (y, x) -> ass.(y).[x] = c) yxs) ['S'; 'T'] in
  Printf.printf "%d\n" @@
  if sy = ty || sx = tx then -1
  else G.max_flow (2 + h + w)
    (List.concat @@ List.map (fun (y, x) ->
      match ass.(y).[x] with
      | '.' -> []
      | 'S' -> [(`Source, `Col x, max_int, 0); (`Source, `Row y, max_int, 0)]
      | 'T' -> [(`Sink, `Col x, 0, max_int); (`Sink, `Row y, 0, max_int)]
      | 'o' -> [(`Col x, `Row y, 1, 1)]) yxs) `Source `Sink


Measured memory_bytes: 8832