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 C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Competitive
{
    internal class Solution
    {
        public int H, W;
        public char[,] MP;
        public long MOD = 1000000007;
        public Graph G;
        public int V;

        public void Run()
        {
            {
                var line = Input.ReadIntArray();
                H = line[0];
                W = line[1];
            }

            MP = new char[H, W];
            for (int i = 0; i < H; i++)
            {
                var line = Console.ReadLine();
                for (int j = 0; j < W; j++)
                {
                    MP[i, j] = line[j];
                }
            }

            V = H + W + 2;
            int st = H + W;
            int ed = H + W + 1;
            G = new Graph(V);
            for (int y = 0; y < H; y++)
            for (int x = 0; x < W; x++)
            {
                if (MP[y, x] == 'o')
                {
                    {
                        int fr = y;
                        int to = H + x;
                        int cap = 1;
                        var e1 = new Edge(fr, to, cap);
                        var e2 = new Edge(to, fr, 0);
                        e1.Rev = e2;
                        e2.Rev = e1;
                        G[fr].Edges.Add(e1);
                        G[to].Edges.Add(e2);
                    }

                    {
                        int fr = H + x;
                        int to = y;
                        int cap = 1;
                        var e1 = new Edge(fr, to, cap);
                        var e2 = new Edge(to, fr, 0);
                        e1.Rev = e2;
                        e2.Rev = e1;
                        G[fr].Edges.Add(e1);
                        G[to].Edges.Add(e2);
                    }
                }

                if (MP[y, x] == 'S')
                {
                    {

                        int fr = st;
                        int to = y;
                        int cap = 1000;
                        var e1 = new Edge(fr, to, cap);
                        var e2 = new Edge(to, fr, 0);
                        e1.Rev = e2;
                        e2.Rev = e1;
                        G[fr].Edges.Add(e1);
                        G[to].Edges.Add(e2);
                    }
                    {

                        int fr = st;
                        int to = H + x;
                        int cap = 1000;
                        var e1 = new Edge(fr, to, cap);
                        var e2 = new Edge(to, fr, 0);
                        e1.Rev = e2;
                        e2.Rev = e1;
                        G[fr].Edges.Add(e1);
                        G[to].Edges.Add(e2);
                    }
                }

                if (MP[y, x] == 'T')
                {
                    {

                        int fr = y;
                        int to = ed;
                        int cap = 1000;
                        var e1 = new Edge(fr, to, cap);
                        var e2 = new Edge(to, fr, 0);
                        e1.Rev = e2;
                        e2.Rev = e1;
                        G[fr].Edges.Add(e1);
                        G[to].Edges.Add(e2);
                    }
                    {

                        int fr = H + x;
                        int to = ed;
                        int cap = 1000;
                        var e1 = new Edge(fr, to, cap);
                        var e2 = new Edge(to, fr, 0);
                        e1.Rev = e2;
                        e2.Rev = e1;
                        G[fr].Edges.Add(e1);
                        G[to].Edges.Add(e2);
                    }
                }
            }

            var ff = new FordFulkerson(G);
            int ret = ff.MaxFlow(st, ed);
            Console.WriteLine(ret >= 1000 ? -1 : ret);
        }
    }

    // libs ----------
    // 最大流問題、最悪で計算量はO(F*E)
    class FordFulkerson
    {
        public bool[] Used;
        int N;
        public Graph G;
        private int INF = 1000000;

        public FordFulkerson(Graph G)
        {
            this.G = G;
            N = G.Nodes.Count;
        }

        public int MaxFlow(int s, int t)
        {
            int ret = 0;
            while (true)
            {
                Used = new bool[N];
                int flow = DFS(s, t, INF);
                if (flow == 0) return ret;
                ret += flow;
            }
        }

        public int DFS(int ss, int tt, int flow)
        {
            if (ss == tt) return flow;
            Used[ss] = true;
            foreach (var e in G[ss].Edges)
            {
                if (!Used[e.To] && e.Cap > 0)
                {
                    int f = DFS(e.To, tt, Math.Min(flow, e.Cap));
                    if (f > 0)
                    {
                        e.Cap -= f;
                        e.Rev.Cap += f;
                        return f;
                    }
                }
            }

            return 0;
        }
    }

    internal class Graph
    {
        public List<Node> Nodes;

        public Node this[int i]
        {
            set { Nodes[i] = value; }
            get { return Nodes[i]; }
        }

        public Graph(int N)
        {
            Nodes = new List<Node>();
            for (int i = 0; i < N; i++)
            {
                Nodes.Add(new Node(i));
            }
        }

    }

    internal class Node
    {
        public List<Edge> Edges;
        public int No;

        public Node(int no)
        {
            this.No = no;
            Edges = new List<Edge>();
        }
    }

    internal class Edge
    {
        public int From;
        public int To;
        public int Cap;
        public Edge Rev;

        public Edge(int fr, int to, int cap)
        {
            From = fr;
            To = to;
            Cap = cap;
        }

    }

    // common ----------

    internal static class Input
    {
        public static string ReadString()
        {
            string line = Console.ReadLine();
            return line;
        }

        public static int ReadInt()
        {
            string line = Console.ReadLine();
            return int.Parse(line);
        }

        public static int[] ReadIntArray()
        {
            string line = Console.ReadLine();
            return line.Split(' ').Select(int.Parse).ToArray();            
        }

        public static long ReadLong()
        {
            string line = Console.ReadLine();
            return long.Parse(line);
        }

        public static long[] ReadLongArray()
        {
            string line = Console.ReadLine();
            return line.Split(' ').Select(long.Parse).ToArray();
        }

        public static double[] ReadDoubleArray()
        {
            string line = Console.ReadLine();
            return line.Split(' ').Select(double.Parse).ToArray();
        }
    }
    
    internal class Program
    {
        public static void Main(string[] args)
        {
            var s = new Solution();
            s.Run();
        }
    }
}