#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <deque>
#include <functional>
#include <iomanip>
#include <locale>
#include <iostream>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#define REP(i,n) for(int i=0;i<(int)(n);i++)
#define ALL(x) (x).begin(),(x).end()

using namespace std;

using ll = long long;
using ld = long double;

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }
template <typename T> int len(const T &x) { return x.size(); }

template<typename T> T inf;
template<> constexpr int inf<int> = 1e9;
template<> constexpr ll inf<ll> = 1e18;
template<> constexpr ld inf<ld> = 1e30;

template<typename T>
vector<T> table(int n, T v) { return vector<T>(n, v); }

template <class... Args>
auto table(int n, Args... args) {
  auto val = table(args...);
  return vector<decltype(val)>(n, move(val));
}

struct yes_no : numpunct<char> {
  string_type do_truename()  const { return "Yes"; }
  string_type do_falsename() const { return "No"; }
};

template <typename Edge>
typename Edge::Flow augment(vector<vector<Edge>> &g,
                            vector<int> &d, vector<int> &iter,
                            int v, int t, const typename Edge::Flow &f) {
  if (v == t) return f;
  for (int &i = iter[v]; i < (int)g[v].size(); i++) {
    auto &e = g[v][i];
    if (e.cap > 0 && d[v] < d[e.to]) {
      typename Edge::Flow ff = augment(g, d, iter, e.to, t, min(f, e.cap));
      if (ff > 0) {
        e.cap -= ff;
        g[e.to][e.rev].cap += ff;
        return ff;
      }
    }
  }
  return 0;
}

template <typename Edge>
typename Edge::Flow max_flow(vector<vector<Edge>> &g, int s, int t,
                             typename Edge::Flow zero = 0) {
  using Flow = typename Edge::Flow;
  const int V = g.size();
  Flow flow = zero;
  for (;;) {
    vector<int> d(V, -1);
    queue<int> que;
    d[s] = zero;
    que.push(s);
    while(!que.empty()) {
      int v = que.front(); que.pop();
      for (const auto &e: g[v]) {
        if (e.cap <= zero || d[e.to] >= zero) continue;
        d[e.to] = d[v] + 1;
        que.push(e.to);
      }
    }
    if (d[t] < zero) return flow;
    vector<int> iter(V, 0);
    Flow f;
    while ((f = augment(g, d, iter, s, t, inf<Flow>)) > 0) flow += f;
  }
}

struct Edge {
  using Flow = int;
  int to, rev;
  Flow cap;
  Edge(int t, Flow f, int r) : to(t), rev(r), cap(f) {}
};

using Graph = vector<vector<Edge>>;

void add_edge(Graph &g, int from, int to, Edge::Flow cap) {
  g[from].emplace_back(to, cap, (int)g[to].size());
  g[to].emplace_back(from, 0, (int)g[from].size() - 1);
}

void solve(ll H, ll W, vector<string> a) {
  Graph g(H * W * 2 + H + W);
  int s = -1, t = -1;
  REP(i,H) REP(j,W) {
    add_edge(g, (i * W + j) * 2 + 1, H * W * 2 + i, inf<int>);
    add_edge(g, (i * W + j) * 2 + 1, H * W * 2 + H + j, inf<int>);
    add_edge(g, H * W * 2 + i, (i * W + j) * 2, inf<int>);
    add_edge(g, H * W * 2 + H + j, (i * W + j) * 2, inf<int>);
    if (a[i][j] == 'o') {
      add_edge(g, (i * W + j) * 2, (i * W + j) * 2 + 1, 1);
    }
    if (a[i][j] == 'S') s = i * W + j;
    if (a[i][j] == 'T') t = i * W + j;
  }
  const int res = max_flow(g, s * 2 + 1, t * 2);
  if (res > H * W) cout << -1 << endl;
  else cout << res << endl;
}

int main() {
  locale loc(locale(), new yes_no);
  cout << boolalpha << setprecision(12) << fixed;
  cout.imbue(loc);
	ll W;
	ll H;
	scanf("%lld", &H);
	vector<string> a(H-1+1);
	scanf("%lld", &W);
	for (int i = 0 ; i <= H-1 ; i++) {
	  cin >> a[i];
	}
	solve(H, W, a);
	return 0;
}


Measured memory_bytes: 2872