#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

#define CIN_ONLY if(1)
struct cww{cww(){
    CIN_ONLY{
        ios::sync_with_stdio(false);cin.tie(0);
    }
}}star;
#define fin "\n"
#define FOR(i,bg,ed) for(int i=(bg);i<(ed);i++)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()
#define fi first
#define se second
#define pb push_back
#define DEBUG if(0)
#define REC(ret, ...) std::function<ret (__VA_ARGS__)>
template <typename T>inline bool chmin(T &l,T r)
{bool a=l>r;if(a)l=r;return a;}
template <typename T>inline bool chmax(T &l,T r)
{bool a=l<r;if(a)l=r;return a;}
template <typename T>
istream& operator>>(istream &is,vector<T> &v){
    for(auto &it:v)is>>it;
    return is;
}

struct edge{
    int flow,to,rev;
};
typedef vector<edge> E;
typedef vector<E> Graph;
#define pb push_back
void addedge(Graph&g,int from,int to,int f){
    int x=g[from].size();
    int y=g[to].size();
    g[from].pb(edge{f,to,y});
    g[to].pb(edge{0,from,x});
}

vector<int> bfs(Graph& G,int s){
    int N = G.size();
    queue<int> que;
    vector<int> dist(N,-1);
    dist[s] = 0;
    que.push(s);
    for(;!que.empty();que.pop()){
        auto v=que.front();
        for(auto& e : G[v])
            if(e.flow>0&&dist[e.to]==-1){
                dist[e.to] = dist[v] + 1;
                que.push(e.to);
        }
    }
    return dist;
}

int maxflow(Graph& G,int s,int t){
    int res=0;
    int N = G.size();
    while(true){
        auto dist = bfs(G,s);
        if(dist[t] < 0)break;
        vector<unsigned> iter(N,0);
        std::function<int(int,int)> dfs=[&](int v,int f){
            if(v==s)return f;
            for(auto &i = iter[v]; i < G[v].size(); i++){
                edge &e = G[v][i];
                edge &re = G[e.to][e.rev];
                if(re.flow>0 && dist[v] >dist[e.to]){
                    int d=dfs(e.to,min(f,re.flow));
                    if(d>0){e.flow+=d;re.flow-=d;return d;}
                }
            }
            return 0;
        };
        int f;
        while((f=dfs(t,114514))> 0)res+=f;
    }
    return res;
}
vector<string> wrap(vector<string> vs,char c){
    int R=vs.size();
    int C=vs[0].size();
    vector<string> res(R+200,string(C+200,c));
    REP(i,R)REP(j,C)res[i+100][j+100]=vs[i][j];
    return res;
}

int dr[]={0,1,0,-1};
int dc[]={1,0,-1,0};
typedef vector<int> V;
typedef vector<V> VV;
int main(){
    int R,C;
    cin>>R>>C;
    vector<string> S(R);
    cin>>S;
    S=wrap(S,'.');
    R+=100;
    C+=100;
    int n=0;
    VV in(R,V(C));
    VV out(R,V(C));
    int st=0,gl=0;

    FOR(i,100,R)FOR(j,100,C)in[i][j]=n++;
    FOR(i,100,R)FOR(j,100,C)out[i][j]=n++;
    
    Graph g(n);
    FOR(i,100,R)FOR(j,100,C){
        if(S[i][j]=='o'){
            addedge(g,in[i][j],out[i][j],1);
            REP(k,4)REP(l,100){
                int nr=i+dr[k]*l;
                int nc=j+dc[k]*l;
                if(S[nr][nc]=='o')addedge(g,out[i][j],in[nr][nc],1);
            }
        }
        if(S[i][j]=='S'){
            st=out[i][j];
            REP(k,4)REP(l,100){
                int nr=i+dr[k]*l;
                int nc=j+dc[k]*l;
                if(S[nr][nc]=='o')addedge(g,out[i][j],in[nr][nc],1);
                if(S[nr][nc]=='T'){
                    cout<<-1<<endl;
                    return 0;
                }
            }
        }
        if(S[i][j]=='T'){
            gl=in[i][j];
            REP(k,4)REP(l,100){
                int nr=i+dr[k]*l;
                int nc=j+dc[k]*l;
                if(S[nr][nc]=='o')addedge(g,out[nr][nc],in[i][j],1);
            }
        }
    }
    //REP(i,R+1)cout<<S[i]<<endl;
    //cout<<st<<" "<<gl<<endl;
    cout<<maxflow(g,st,gl)<<endl;
    return 0;
}


Measured memory_bytes: 63104