#include <bits/stdc++.h>

using namespace std;

void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  cerr << " " << to_string(H);
  debug_out(T...);
}
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

#define rep(i,n) for(int i=0; i<(int)(n); i++)
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

using ll = long long;
using P = pair<ll, ll>;

//constexpr ll mod = 998244353;
constexpr ll mod = 1e9+7;
const double PI = acos(-1.0);
mt19937_64 engine(chrono::steady_clock::now().time_since_epoch().count());

struct {
    struct edge { int to; ll cost; int rev; };
    int N;
    vector<vector<edge>> graph;
    vector<int> level;
    vector<int> iter;

    void init(int n) {
      graph.resize(n+1, vector<edge>());
      level.resize(n+1);
      iter.resize(n+1);
      N=n+1;
    }

    void add_edge(int from, int to, ll cost) {
      int r1 = graph[from].size();
      int r2 = graph[to].size();
      graph[from].push_back((edge){to, cost, r2});
      graph[to].push_back((edge){from, 0, r1});
    }

    void add_edge2(int from, int to, ll cost) {
      int r1 = graph[from].size();
      int r2 = graph[to].size();
      graph[from].push_back((edge){to, cost, r2});
      graph[to].push_back((edge){from, cost, r1});
    }

    void bfs(int s) {
      for(int i=0; i<N; i++) level[i] = -1;
      queue<int> que;
      level[s] = 0; que.push(s);
      while(!que.empty()) {
        int v = que.front(); que.pop();
        for(auto& e: graph[v]) {
          if (e.cost > 0 && level[e.to] < 0) {
            level[e.to] = level[v] + 1;
            que.push(e.to);
          }
        }
      }
    }

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

    ll max_flow(int s, int t) {
      ll flow = 0;
      while(true) {
        bfs(s);
        if (level[t] < 0) return flow;
        for(int i=0; i<N; i++) iter[i] = 0;
        ll f;
        while((f = dfs(s, t, LLONG_MAX/4)) > 0) {
          flow += f;
        }
      }
    }
} D;

signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  D.init(250);

  int h, w; cin >> h >> w;
  rep(i, h) {
    rep(j, w) {
      char c; cin >> c;
      int k = j+100;
      if (c == 'o') {
        D.add_edge2(i, k, 1);
      } else if (c == 'S') {
        D.add_edge(210, i, INT_MAX);
        D.add_edge(210, k, INT_MAX);
      } else if (c == 'T') {
        D.add_edge(i, 220, INT_MAX);
        D.add_edge(k, 220, INT_MAX);
      }
    }
  }

  ll ans = D.max_flow(210, 220);
  debug(ans);
  if (ans >= INT_MAX) ans = -1;
  cout << ans << endl;
}

Measured memory_bytes: 896