Problem:
Score : 800 points

Problem Statement

There is a pond with a rectangular shape.
The pond is divided into a grid with H rows and W columns of squares.
We will denote the square at the i-th row from the top and j-th column from the left by (i,\ j).

Some of the squares in the pond contains a lotus leaf floating on the water.
On one of those leaves, S, there is a frog trying to get to another leaf T.
The state of square (i,\ j) is given to you by a character a_{ij}, as follows:

. : A square without a leaf.

o : A square with a leaf floating on the water.

S : A square with the leaf S.

T : A square with the leaf T.

The frog will repeatedly perform the following action to get to the leaf T: "jump to a leaf that is in the same row or the same column as the leaf where the frog is currently located."

Snuke is trying to remove some of the leaves, other than S and T, so that the frog cannot get to the leaf T.
Determine whether this objective is achievable. If it is achievable, find the minimum necessary number of leaves to remove.

Constraints

2 ≤ H, W ≤ 100

a_{ij} is ., o, S or T.

There is exactly one S among a_{ij}.

There is exactly one T among a_{ij}.

Input

Input is given from Standard Input in the following format:

H W
a_{11} ... a_{1W}
:
a_{H1} ... a_{HW}

Output

If the objective is achievable, print the minimum necessary number of leaves to remove.
Otherwise, print -1 instead.

Sample Input 1

3 3
S.o
.o.
o.T

Sample Output 1

2

Remove the upper-right and lower-left leaves.

Sample Input 2

3 4
S...
.oo.
...T

Sample Output 2

0

Sample Input 3

4 3
.S.
.o.
.o.
.T.

Sample Output 3

-1

Sample Input 4

10 10
.o...o..o.
....o.....
....oo.oo.
..oooo..o.
....oo....
..o..o....
o..o....So
o....T....
....o.....
........oo

Sample Output 4

5

Solution in OCaml (4.02.3) (judge verdict: Accepted)

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