#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using Pi = pair<int, int>;
using Pl = pair<ll, ll>;
using vint = vector<int>;
using vll = vector<ll>;
template<typename T> using uset = unordered_set<T>;
template<typename T1, typename T2> using umap = unordered_map<T1, T2>;

constexpr int INF = (1 << 30) - 1;
constexpr ll LLINF = 1LL << 60;
constexpr int dy[] = {1, 0, -1, 0, 1, -1, -1, 1};
constexpr int dx[] = {0, 1, 0, -1, 1, 1, -1, -1};
constexpr char el = '\n';
constexpr int mod = 1000000007;

template<typename T> T gcd(T a, T b) { return (b ? gcd(b, a % b) : a); }
template<typename T> T lcm(T a, T b) { return (a / gcd(a, b) * b); }
template<typename T1, typename T2> inline void chmin(T1 &a, T2 b) { if (a > b) a = b; }
template<typename T1, typename T2> inline void chmax(T1 &a, T2 b) { if (a < b) a = b; }

template<typename T>
ostream& operator <<(ostream &os, vector<T> &v) {
        for (auto &u : v) os << u << endl;
        return (os);
}

template<typename T>
istream& operator >>(istream &is, pair<vector<T>&, int> v) {
        while (v.second--) {
                T a;
                v.first.push_back(is >> a, a);
        }
        return (is);
}

template<typename T>
istream& operator >>(istream &is, vector<T> &v) {
        for (auto &u : v) is >> u;
        return (is);
}

template<typename T>
struct Dinic {
        struct Edge {
                int to, rev;
                T cap;
                Edge () {}
                Edge (int to, int rev, T cap) : to(to), rev(rev), cap(cap) {}
        };

        vector<vector<Edge>> G;
        vector<int> level, itr;
        const T INF;
        int timestamp;
        int V;

        Dinic(int size) : V(size), INF(numeric_limits<T>::max()), timestamp(0) {
                G.resize(size);
        }

        void add_edge(int from, int to, T cap) {
                G[from].emplace_back(to, (int)G[to].size(), cap);
                G[to].emplace_back(from, (int)G[from].size() - 1, 0);
        }

        void bfs(int s) {
                level.assign(V, -1);
                queue<int> que;

                level[s] = 0; que.push(s);
                while (!que.empty()) {
                        int v = que.front(); que.pop();
                        for (auto &e : G[v]) {
                                if (e.cap > 0 && level[e.to] == -1) {
                                        level[e.to] = level[v] + 1;
                                        que.push(e.to);
                                }
                        }
                }
        }

        T dfs(int v, int t, T flow) {
                if (v == t) return (flow);
                for (int& i = itr[v]; i < (int)G[v].size(); i++) {
                        Edge &e = G[v][i];
                        if (e.cap > 0 && level[e.to] > level[v]) {
                                T d = dfs(e.to, t, min(flow, e.cap));
                                if (d > 0) {
                                        e.cap -= d;
                                        G[e.to][e.rev].cap += d;
                                        return (d);
                                }
                        }
                }
                return (0);
        }

        T max_flow(int s, int t) {
                T flow = 0, f;
                while (bfs(s), level[t] >= 0) {
                        itr.assign(V, 0);
                        while ((f = dfs(s, t, INF)) > 0) flow += f;
                }
                return (flow);
        }
};

int main() {
        int H, W;
        cin >> H >> W;
        vector<string> A(H); cin >> A;
        Dinic<int> g((H + 1) * (W + 1) * 2);
        int start, goal;
        int big = 100000;
        for (int i = 0; i < H; i++) {
                for (int j = 0; j < W; j++) {
                        int pos = (i * (W + 1) + j) * 2;
                        int posr = (i * (W + 1) + W) * 2;
                        int posc = (H * (W + 1) + j) * 2;
                        if (A[i][j] == '.') continue;
                        if (A[i][j] == 'S') start = pos + 1;
                        if (A[i][j] == 'T') goal = pos;
                        g.add_edge(pos, pos + 1, 1);
                        g.add_edge(pos + 1, posr, big);
                        g.add_edge(pos + 1, posc, big);
                        g.add_edge(posr + 1, pos, big);
                        g.add_edge(posc + 1, pos, big);
                }
        }
        for (int i = 0; i < H; i++) {
                int posr = (i * (W + 1) + W) * 2;
                g.add_edge(posr, posr + 1, big);
        }
        for (int j = 0; j < W; j++) {
                int posc = (H * (W + 1) + j) * 2;
                g.add_edge(posc, posc + 1, big);
        }


        int flow = g.max_flow(start, goal);
        if (flow >= big) {
                cout << -1 << endl;
        } else {
                cout << flow << endl;
        }
        return (0);
}

Measured memory_bytes: 2816