#include <bits/stdc++.h>
#define PII pair<int, int>
#define LL long long
using namespace std;
const int MAXN = 105;
const int MAXV = 2 * MAXN * MAXN;
const int maxn = MAXV;
const LL INF = (LL)1e9 + 5;
const LL MOD = 1000000007;

template<class T>
struct Flow {
    struct Edge{
        int f,to;
        T c;
        Edge(int _f,int _to,T _c):f(_f),to(_to),c(_c){}
    };

	// IMPORETANT
    // maxn is the number of vertices in the graph
    // Not the N in the problem statement!!
    vector<int> G[maxn];
    vector<Edge> es;
    int level[maxn],st, end, n;
    int cur[maxn];

    void init(int _n){
        n = _n;
        es.clear();
        for(int i=0; i<=n; i++) G[i].clear();
    }

    void add_edge(int f,int t,T c, bool directed=true){
        es.push_back(Edge(f,t,c)); G[f].push_back(es.size()-1);
        es.push_back(Edge(t,f,directed?0:c)); G[t].push_back(es.size()-1);
    }

    bool BFS(int s,int t){
        queue<int> Q;
        for(int i=0; i<=n; i++) level[i] = 0;
        level[s] = 1;
        Q.push(s);
        while(!Q.empty()){
            int x = Q.front(); Q.pop();
            for(int i=0; i<G[x].size(); i++){
                Edge e = es[ G[x][i] ];
                if(e.c==0 || level[e.to]) continue;
                level[e.to] = level[x] + 1;
                Q.push(e.to);
            }
        }
        return level[t]!=0;
    }

    T DFS(int s,T cur_flow){ // can't exceed c
        if(s==end) return cur_flow;

        T ans = 0, temp, total = 0;

        for(int& i=cur[s]; i<G[s].size(); i++){
            Edge &e = es[ G[s][i] ];
            if(e.c==0 || level[e.to]!=level[s]+1) continue;
            temp = DFS(e.to, min(e.c, cur_flow));
            if(temp!=0){
                e.c -= temp;
                es[G[s][i]^1].c += temp;
                cur_flow -= temp;
                total += temp;
                if(cur_flow==0) break;
            }
        }
        return total;
    }

    T max_flow(int s,int t){
    	/* If you want to incrementally doing maxFlow, 
		   you need to add the result manually.
		   This function returns difference in that case. */
        T ans = 0;
        st = s, end = t;
        while(BFS(s,t)){
            while(true){
                memset(cur, 0, sizeof(cur));
                T temp = DFS(s,INF);
                if(temp==0) break;
                ans += temp;
            }
        }
        return ans;
    }
};

int R, C, sr, sc, tr, tc;
char mp[MAXN][MAXN];
Flow<int> mf;

int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);

	cin >> R >> C;
	
	mf.init(2 * R * C + 5);
	for (int i = 0; i < R; i++) {
		for (int j = 0; j < C; j++) {
			int vin = i * C + j, vout = vin + R * C;
			char ch;
			cin >> ch;
			mp[i][j] = ch;
			if (ch == 'o') {
				mf.add_edge(vin, vout, 1);
			}
			else if (ch == 'S') {
				mf.add_edge(vin, vout, INF);
				sr = i;
				sc = j;
			}
			else if (ch == 'T') {
				mf.add_edge(vin, vout, INF);
				tr = i;
				tc = j;
			}
		}
	}
	for (int i = 0; i < R; i++) {
		for (int j = 0; j < C; j++) {
			int vout = i * C + j + R * C;
			for (int ii = 0; ii < R; ii++) {
				if (ii == i || mp[ii][j] == '.') continue;
				int uin = ii * C + j;
				mf.add_edge(vout, uin, INF);
			}
			for (int jj = 0; jj < C; jj++) {
				if (jj == j || mp[i][jj] == '.') continue;
				int uin = i * C + jj;
				mf.add_edge(vout, uin, INF);
			}
		}
	}
	
	if (sr == tr || sc == tc) {
		cout << "-1\n";
		return 0;
	}
	
	int ans = mf.max_flow(sr * C + sc, tr * C + tc);
	cout << ans << '\n';

	return 0;
}

Measured memory_bytes: 69792