#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <set>
#include <queue>
#include <stack>
#include <tuple>
#include <cmath>
#include <iomanip>
#include <map>
#include <cstring>
#include <functional>
#include <cctype>
#include <locale>
#define ll long long
#define rep(i,n) for(int i=0;i<(n);i++)
#define rrep(i,n) for(int i=n-1;i>=0;i--)
#define fi first
#define se second
#define pb push_back
#define ALL(a) (a).begin(),(a).end()
using namespace std;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}
typedef pair<int,int> P;
typedef pair<long long,long long> Pll;
#define fout(num) cout << fixed << setprecision(20) << (num) << endl
//s[i]=tolower(s[i]); islower(s[i]); cout << tolower(s[i])はバグ
//vector<vector<ll>> dp(n,vector<ll>(n))
//2-dim:vector<vector<Type>> vv(n, vector<Type>(m, d));
//3-dim:vector<vector<vector<Type>>> vvv(n, vector<vector<Type>>(m, vector<Type>(l, d)));
template<typename T>
struct Dinic{
    struct edge{
        int to,rev;
        T cap;
    };
    vector<vector<edge>> G;
    vector<pair<int, int>> pos;
    vector<int> level; //dist
    vector<int> iter; //visited
    const T INF;
    Dinic(int n):INF(numeric_limits<T>::max()){
        G.resize(n);
    }
    void add_edge(int from,int to, T cap){
        pos.push_back({from,G[from].size()});
        G[from].push_back(edge{to,int(G[to].size()),cap});
        G[to].push_back(edge{from,int(G[from].size()-1),0});
    }
    void add_edge_2(int from,int to, T cap){
        add_edge(from,to,cap);
        add_edge(to,from,cap);
    }
    struct Edge{
        int to,rev;
        T cap,flow;
    };
    Edge get_edge(int x){
        auto _e = G[pos[x].first][pos[x].second];
        auto _re = G[_e.to][_e.rev];
        /* from,to,cap,flow */
        return (Edge){pos[x].first, _e.to, _e.cap + _re.cap, _re.cap};
    }
    bool bfs(int s,int t){
        level.assign(G.size(),-1);
        queue<int> que;
        level[s] = 0;
        que.push(s);
        while(!que.empty()) {
          int fr = que.front();
          que.pop();
          for(auto &e : G[fr]) {
            if(e.cap > 0 && level[e.to] == -1) {
              level[e.to] = level[fr] + 1;
              que.push(e.to);
            }
          }
        }
        return (level[t] != -1);
    }
    T dfs(int idx,const int t,T flow){
        if(idx==t) return flow;
        for(int &i=iter[idx];i<G[idx].size();i++){
            edge &e=G[idx][i];
            if(e.cap>0 && level[idx]<level[e.to]){
                T resflow=dfs(e.to,t,min(flow,e.cap));
                if(resflow>0){
                    e.cap-=resflow;
                    G[e.to][e.rev].cap+=resflow;
                    return resflow;
                }
            }
        }
        return 0;
    }
    T max_flow(int s,int t,T lim){
        T retflow=0;
        while(retflow<lim&&bfs(s,t)){
            iter.assign(G.size(),0);
            if(level[t]<0) return retflow;
            T flow=0;
            while((flow=dfs(s,t,lim-flow))>0){
                retflow+=flow;
            }
        }
        return retflow;
    }
    T max_flow(int s,int t){ return max_flow(s,t,INF); }
};
signed main(){
    std::cin.tie(nullptr);
    std::ios_base::sync_with_stdio(false);
    int h,w; cin >> h >> w;
    Dinic<ll> Dn(h+w+2);
    vector<string> s(h);
    rep(i,h) cin >> s[i];
    ll INF = 1e9;
    rep(i,h){
        rep(j,w){
            if(s[i][j]=='S'){
                Dn.add_edge(0,i+1,INF);
                Dn.add_edge(0,h+j+1,INF);
            }
            if(s[i][j]=='T'){
                Dn.add_edge(i+1,h+w+1,INF);
                Dn.add_edge(h+j+1,h+w+1,INF);
            }
            if(s[i][j]=='o'){
                Dn.add_edge_2(i+1,h+j+1,1);
            }
        }
    }
    rep(i,h){
        rep(j,w){
            if(s[i][j]=='S'){
                rep(k,h){
                    if(s[k][j]=='T'){
                        cout << -1 << endl;
                        return 0;
                    }
                }
                rep(k,w){
                    if(s[i][k]=='T'){
                        cout << -1 << endl;
                        return 0;
                    }
                }
            }
        }
    }
    ll ans=Dn.max_flow(0,h+w+1);
    cout << ans << endl;
}




Measured memory_bytes: 4308