#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i = 0; i < (int)n; i++)
const int INF = 1e9;
struct edge {int to, cap, rev;};

template <typename T> 
class Dinic {
public:
    Dinic(int V);
    void add_edge(int from, int to, T cap);
    T max_flow(int s, int t);

private:
    void bfs(int s);
    T dfs(int v, int t, T f);
    vector<vector<edge>> g;
    vector<int> level;
    vector<int> iter;
};

template <typename T> 
Dinic<T>::Dinic(int V){
    g = vector<vector<edge>> (V,vector<edge>());
    level = vector<int>(V);
    iter = vector<int>(V);
}

template <typename T> 
void Dinic<T>::add_edge(int from, int to, T cap) {
    g[from].push_back((edge){to, cap, (int)g[to].size()});
    g[to].push_back((edge){from, (T)0, (int)g[from].size()-1});
}

template <typename T> 
void Dinic<T>::bfs(int s){
    rep(i,level.size()) level[i] = -1;
    queue<int> que;
    level[s] = 0;
    que.push(s);
    while(!que.empty()){
        int v = que.front(); que.pop();
        rep(i,g[v].size()){
            edge &e = g[v][i];
            if(e.cap > 0 && level[e.to] < 0) {
                level[e.to] = level[v] + 1;
                que.push(e.to);
            }
        }
    }
}

template <typename T> 
T Dinic<T>::dfs(int v, int t, T 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]) {
            T 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;
}

template <typename T> 
T Dinic<T>::max_flow(int s, int t) {
    T flow = 0;
    while(true){
        bfs(s);
        if(level[t] < 0) return flow;
        rep(i,iter.size()) iter[i] = 0;
        T f;
        while((f = dfs(s,t,INF)) > 0){
            flow += f;
        }
    }
}

int main(){
    int h, w;
    cin >> h >> w;
    char a[h][w];
    int s, t;
    rep(i,h){
        rep(j,w) {
            cin >> a[i][j];
            if(a[i][j] == 'S') s = i*w+j;
            if(a[i][j] == 'T') t = i*w+j;
        }
    }
    if(s%w == t%w || s/w == t/w){
        cout << -1 << endl;
        return 0;
    }
    Dinic<int> dinic(2*h*w);
    rep(i,h) {
        rep(j,w){
            if(a[i][j] == 'o'){
                dinic.add_edge(i*w+j,h*w+i*w+j,1);
                for(int k = 1; k < h; k++){
                    if(a[(i+k)%h][j] == 'o' || a[(i+k)%h][j] == 'S' || a[(i+k)%h][j] == 'T') dinic.add_edge(h*w+i*w+j,((i+k)%h)*w+j,1);
                }
                for(int k = 1; k < w; k++){
                    if(a[i][(j+k)%w] == 'o' || a[i][(j+k)%w] == 'S' || a[i][(j+k)%w] == 'T') dinic.add_edge(h*w+i*w+j,i*w+(j+k)%w,1);
                }
            } else if(a[i][j] == 'S' || a[i][j] == 'T'){
                for(int k = 1; k < h; k++){
                    if(a[(i+k)%h][j] == 'o' || a[(i+k)%h][j] == 'S' || a[(i+k)%h][j] == 'T') dinic.add_edge(i*w+j,((i+k)%h)*w+j,1);
                }
                for(int k = 1; k < w; k++){
                    if(a[i][(j+k)%w] == 'o' || a[i][(j+k)%w] == 'S' || a[i][(j+k)%w] == 'T') dinic.add_edge(i*w+j,i*w+(j+k)%w,1);
                }
            }
        }
    }
    cout << dinic.max_flow(s,t) << endl;
    return 0;
}

Measured memory_bytes: 62592