#include "bits/stdc++.h"
using namespace std;
#define OUT(x)                cout << #x << " = " << x << endl; 
#define rep(i, n)             for (int (i) = 0; (i) < (int)(n); (i)++)
#define rer(i, l, r)          for (int (i) = (int)(l); (i) <= (int)(r); (i)++)
#define reu(i, l, r)          for (int (i) = (int)(l); (i) < (int)(r); (i)++)
#define each(i, v)            for (auto i : v)
#define all(x)                (x).begin(), (x).end()
#define rall(x)               (x).rbegin(), (x).rend()
#define pb(x)                 push_back(x)
#define bp(x)                 __builtin_popcount(x)
#define mp(x, y)              make_pair((x), (y))
#define fi                    first
#define se                    second
#define setp(x)               setprecision(x)
#define mset(m, v)            memset(m, v, sizeof(m))
#define sz(x)                 (int)(x.size())
static const int INF        = 0x3f3f3f3f;
static const long long INFL = 0x3f3f3f3f3f3f3f3fLL;
static const int MOD        = 1000000007;
static const double PI      = 3.14159265358979;

//#define int                   long long

typedef vector<double>        vd;
typedef vector<string>        vs;
typedef vector<bool>          vb;
typedef vector<int>           vi;
typedef pair<int, int>        pii;
typedef vector<pii>           vpii;

template<typename T> void pv(T a, T b) { for (T i = a; i != b; i ++) cout << *i << " "; cout << endl; }
template<typename T, typename U> inline void amin(T &x, U y) { if (y < x) x = y; }
template<typename T, typename U> inline void amax(T &x, U y) { if (x < y) x = y; }
int in() { int _x; scanf("%d", &_x); return _x; }
long long lin() {long long _x; scanf("%lld", &_x); return _x; };

struct edge { int to, cap, rev; };
int maximum_flow_destructive(int s, int t, vector<vector<edge> > & g) { // ford fulkerson, O(EF)
    int n = g.size();
    vector<bool> used(n);
    function<int (int, int)> dfs = [&](int i, int f) {
        if (i == t) return f;
        used[i] = true;
        for (edge & e : g[i]) {
            if (used[e.to] or e.cap <= 0) continue;
            int nf = dfs(e.to, min(f, e.cap));
            if (nf > 0) {
                e.cap -= nf;
                g[e.to][e.rev].cap += nf;
                return nf;
            }
        }
        return 0;
    };
    int result = 0;
    while (true) {
        used.clear(); used.resize(n);
        int f = dfs(s, numeric_limits<int>::max());
        if (f == 0) break;
        result += f;
    }
    return result;
}
void add_edge(vector<vector<edge> > & g, int from, int to, int cap) {
    g[from].push_back((edge) {   to, cap, int(g[  to].size()    ) });
    g[  to].push_back((edge) { from,   0, int(g[from].size() - 1) });
}

signed main() { 
        int h, w;
        cin >> h >> w;
        vs f(h);
        rep(y, h) cin >> f[y];
        int s = 0;
        int t = 1;
        vector<vector<edge>> g(2 + h + w);
        rep(y, h) rep(x, w) {
                if (f[y][x] == 'S') {
                        add_edge(g, s, 2 + y, INF);
                        add_edge(g, s, 2 + h + x, INF);
                } else if (f[y][x] == 'T') {
                        add_edge(g, 2 + y, t, INF);
                        add_edge(g, 2 + h + x, t, INF);
                }
                if (f[y][x] != '.') {
                        add_edge(g, 2 + y, 2 + h + x, 1);
                        add_edge(g, 2 + h + x, 2 + y, 1);
                }
        }
        int flow = maximum_flow_destructive(s, t, g);
        if (flow >= INF) flow = -1;
        cout << flow << endl;
        return 0;
}               



Measured memory_bytes: 896