#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>

#define F first
#define S second
//#define int long long
#define ll long long
//#define int  unsigned long long
#define pb push_back
#define double long double

using namespace std;
using namespace __gnu_pbds;
typedef  tree< int , null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
const int N = 10000000;
const int K = 19;
const int mod = 998244353;
int z[N], a[300][300], b[N], n, V, E, nxt[N], head[N], to[N], cap[N], Sx[N], xT[N], dis[N], qf, qb, src, tar, q[N], work[N];
inline void init(int n) {
    memset(head, -1, sizeof(int)*n);
    V = n; E = 0;
}


inline void add_edge(int u, int v, int c) {
  //  cout << u << " " << v << endl;
    to[E] = v; cap[E] = c; nxt[E] = head[u]; head[u] = E++;
    to[E] = u; cap[E] = 0; nxt[E] = head[v]; head[v] = E++;
}


inline void add_edge(int u, int v, int l, int r) {
    if (l) {
        Sx[v] += l, xT[u] += l;
    }
    add_edge(u, v, r - l);
}


inline bool bfs() {
    memset(dis, -1, sizeof(dis));
    qf = qb =0;
    q[qb++] = src; dis[src] = 0;
    while (qf < qb && dis[tar] == -1) {
        int u = q[qf++];
       // cout << u << endl;
        for (int i = head[u]; i >= 0; i = nxt[i]) {
            int v=to[i];
         //   cout << "v = " << v << endl;
            if (dis[v] == -1 && cap[i] > 0) {
                dis[v] = dis[u]+1;
                q[qb++] = v;
            }
        }
    }
    return dis[tar] >= 0;
}


int dfs(int u, int &bot) {
    if (u == tar) {
        return bot;
    }
    for (int &i = work[u]; i >= 0; i = nxt[i]) {
        int v = to[i];
        if (dis[v] != dis[u] + 1 || cap[i] == 0) {
            continue;
        }
        int bot1 = min(bot, cap[i]);
        if (int flow = dfs(v, bot1)) {
            cap[i] -= flow;
            cap[i ^ 1] += flow;
            bot = bot1;
            return flow;
        }
    }
    return 0;
}


int dinic() {
    int ans = 0, bot;
   // cout << "!" << endl;
    while (bfs()) {
    //    cout << tar << " " << src << " " << n << endl;
        memcpy(work, head, sizeof(int)*V);
        int flow = mod;
        while (flow = dfs(src, bot = mod)) {
            ans += flow;
        }
    }
    return ans;
}
main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    //freopen("input.txt", "r", stdin);
    int m;
    cin >> n >> m;
    int s, f;
  srand(52);
    for (int i = 0; i < n; i++){
        string t;

        cin >> t;
        for (int j = 0; j < m; j++){
       //               if ((i != 0 || j != 0) && (i != n - 1 || j != m - 1))
       // a[i][j] = rand() % 2;
            if (t[j] == 'o' || t[j] == 'S' || t[j] == 'T') a[i][j] = 1;
           if (t[j] == 'S') s = i * m + j;
            if (t[j] == 'T') f = i * m + j;
        }
    }
    int k = n + m;
    init(2 * n * m + 10);
    for (int i = 0; i < n; i++){
        for (int j = 0; j < m; j++){
            if (a[i][j] == 0) continue;
            add_edge(i * m + j, i * m + j + n * m, 1 + k * (i * m + j == s || i * m + j == f));
            for (int l = i + 1; l < n; l++){
                if (a[l][j] == 1){
                    add_edge(l * m + j + n * m, i * m + j, k);
                    add_edge(i * m + j + n * m, l * m + j, k);
                }
            }
            for (int l = j + 1; l < m; l++){
                if (a[i][l] == 1){
                  //  cout << "I = " << i << " " << l << endl;
                    add_edge(i * m + l + n * m, i * m + j, k);
                    add_edge(i * m + j + n * m, i * m + l, k);
                }
            }
        }
    }
    add_edge(2 * n * m, s, k);
    add_edge(f + n * m, 2 * n * m + 1, k);
    src = 2 * n * m;
    tar = 2 * n * m + 1;
    if (s % m == f % m || s / m == f / m) cout << -1; else
    cout << dinic();
}


Measured memory_bytes: 102784