#include <bits/stdc++.h>
#define ADD(a, b) a = (a + (ll)b) % mod
#define MUL(a, b) a = (a * (ll)b) % mod
#define MAX(a, b) a = max(a, b)
#define MIN(a, b) a = min(a, b)
#define rep(i, a, b) for(int i = a; i < b; i++)
#define rer(i, a, b) for(int i = a - 1; i >= b; i--)
#define all(a) (a).begin(), (a).end()
#define sec second
#define fst first
#define debug(fmt, ...) Debug(__LINE__, ":", fmt, ##__VA_ARGS__)

using namespace std;

typedef long long ll;
typedef pair<int, int> pi;
typedef pair<int, pi> ppi;
typedef vector<ll> vec;

const int MAX_N = 410;
const double eps = 1e-6;
const ll mod = 1000000007;
const ll inf = 1 << 28;

void Debug() {cout << '\n'; }

template<class FIRST, class... REST> 
void Debug(FIRST arg, REST... rest) { cout << arg << " "; Debug(rest...); }

template<class T>
ostream& operator<< (ostream& out, const vector<T>& v) {
	out << "[";
	if(!v.empty()) {
		rep(i, 0, (int)v.size() - 1) out << v[i] << ", ";
		out << v.back();
	}
	out << "]";
  return out;
}

template<class S, class T>
ostream& operator<< (ostream& out, const pair<S, T>& v) {
	out << "(" << v.first << ", " << v.second << ")";
	return out;
}

///g++ -g3 -std=c++0x -DLOCAL -Wall -ftrapv -D_GLIBCXX_DEBUG -Wl,-stack,268435456 -o
///g++ -O2 -std=c++0x -DLOCAL -Wall -Wl,-stack,268435456 -o

////////////////////////////////////////////////////////////////////////

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

vector<edge> G[MAX_N];
int level[MAX_N];
int iter[MAX_N];

void add_edge(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});
}


void bfs(int s) {
	memset(level, -1, sizeof(level));
	queue<int> que;
	level[s] = 0;
	que.push(s);
	while(!que.empty()) {
		int v = que.front(); que.pop();
		for(int i = 0; i < G[v].size(); i++) {
			edge &e = G[v][i];
			if(e.cap > 0 && level[e.to] == -1) {
				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;
	while(true) {
		bfs(s);
		if(level[t] == -1) return flow;
		memset(iter, 0, sizeof(iter));
		int f;
		while((f = dfs(s, t, inf)) > 0) {
			flow += f;
		}
	}
}

int H, W;
string S[MAX_N];


void solve() {
	cin >> H >> W;
	rep(i, 0, H) {
		cin >> S[i];
		rep(j, 0, W) {
			if(S[i][j] == 'S') {
				add_edge(0, i + 1, inf);
				add_edge(0, j + H + 1, inf);
			}
			if(S[i][j] == 'T') {
				add_edge(i + 1, W + H + 1, inf);
				add_edge(j + H + 1, W + H + 1, inf);
			}
			if(S[i][j] == 'o') {
				add_edge(i + 1, j + H + 1, 1);
				add_edge(j + H + 1, i + 1, 1);
			}
		}
	}
	int res = max_flow(0, W + H + 1);
	if(res >= inf) cout << "-1\n"; 
	else cout << res << "\n";
}

int main() {
	ios::sync_with_stdio(false);
    cin.tie(0);	
    cout << fixed;
	cout.precision(20);
#ifdef LOCAL
    freopen("in.txt", "rt", stdin);
#endif	
	solve();
#ifdef LOCAL
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
	return 0;
}



Measured memory_bytes: 896