#include <bits/stdc++.h>
#define FOR(i, begin, end) for(int i=(begin);i<(end);i++)
#define REP(i, n) FOR(i,0,n)
#define IFOR(i, begin, end) for(int i=(end)-1;i>=(begin);i--)
#define IREP(i, n) IFOR(i,0,n)
#define SORT(a) sort(a.begin(), a.end())
#define REVERSE(a) reverse(a.begin(), a.end())
#define Lower_bound(v, x) distance(v.begin(), lower_bound(v.begin(), v.end(), x))
#define Upper_bound(v, x) distance(v.begin(), upper_bound(v.begin(), v.end(), x))
#define int long long
#define INF 1000000000000000000
using namespace std;

#define ANS(f) if(f) cout << "YES" << endl; else cout << "NO" << endl;

typedef vector<int> vec;
typedef vector<vec> mat;
typedef pair<int, int> Pii;

template<typename T>
void readv(vector<T> &a){ REP(i, a.size()) cin >> a[i]; }
void readi(vector<int> &a){ REP(i, a.size()){cin >> a[i]; a[i]--;} }
void debug(mat m){REP(i, m.size()){ REP(j, m[i].size()){ cout << m[i][j] << ","; } cout << endl; }}

struct edge { int to, cap, rev; };

class Graph
{
public:
    int V;
    vector<vector<edge>> G;
    vec level, iter;

    Graph(int V): V(V){
        G = vector<vector<edge>>(V, vector<edge>(0));
        level = vec(V);
        iter = vec(V);
    }

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

    void bfs(int s){
        memset(&level[0], -1, sizeof(level[0]) * level.size());
        queue<int> que;
        level[s] = 0;
        que.push(s);
        while(!que.empty()){
            int v = que.front(); que.pop();
            REP(i, G[v].size()){
                edge &e = G[v][i];
                if(e.cap > 0 && level[e.to] < 0){
                    level[e.to] = level[v] + 1;
                    que.push(e.to);
                }
            }
        }
    }

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

    int max_flow(int s, int t){
        int flow = 0;
        for(;;){
            bfs(s);
            if(level[t] < 0) return flow;
            memset(&iter[0], 0, sizeof(iter[0]) * iter.size());
            int f;
            while((f = dfs(s, t, INF)) > 0) flow += f;
        }
    }

};

signed main(){

    int H, W; cin >> H >> W;
    int v = 0, s, t, is, js, it, jt;
    char a;
    mat index(H, vec(W, -1));
    Graph G(20000);

    REP(i, H){
        REP(j, W){
            cin >> a;
            if(a == '.') continue;
            if(a == 'S'){
                s = v;
                is = i;
                js = j;
            }
            if(a == 'T'){
                t = v;
                it = i;
                jt = j;
            }
            index[i][j] = v;
            G.add_edge(v, v + 1, 1);
            v += 2;
        }
    }
 
    if(is == it || js == jt){
        cout << -1;
        return 0;
    }
 
    REP(i, H){
        REP(j, W){
            if(index[i][j] == -1) continue;
            REP(i0, H) if(i0 != i && index[i0][j] != -1) G.add_edge(index[i][j] + 1, index[i0][j], INF);
            REP(j0, W) if(j0 != j && index[i][j0] != -1) G.add_edge(index[i][j] + 1, index[i][j0], INF);
        }
    }
 
    cout << G.max_flow(s + 1, t);
    
    return 0;
}

Measured memory_bytes: 124160