#include <bits/stdc++.h>

#define fst(t) std::get<0>(t)
#define snd(t) std::get<1>(t)
#define thd(t) std::get<2>(t)
#define unless(p) if(!(p))
#define until(p) while(!(p))

using ll = std::int64_t;
using P = std::tuple<int,int>;

constexpr int INF = 1001001001;
int H, W;
std::string A[100];
int sy, sx, gy, gx;

struct ResidualGraph{
    int V;
    std::vector<std::vector<std::tuple<int, int, int>>> graph;
     
    ResidualGraph(int V) : V(V), graph(V) { };
 
    void add(int v, int w, int capacity){
        graph[v].emplace_back(w, capacity, graph[w].size());
        graph[w].emplace_back(v, 0, graph[v].size() - 1);
    }
 
    std::vector<std::tuple<int, int, int>>& operator[](int v){
        return graph[v];
    }
};
 
struct Dinitz{
    ResidualGraph &graph;
    std::vector<int> level, lastIndex;
 
    Dinitz(ResidualGraph &graph) : graph(graph), level(graph.V), lastIndex(graph.V) { }
 
    void bfs(int s){
        std::fill(level.begin(), level.end(), -1);
 
        std::queue<int> q;
        q.emplace(s);
        level[s] = 0;
 
        while(!q.empty()){
            int v = q.front();
            q.pop();
             
            for(auto &e : graph[v]){
                int w, cap;
                std::tie(w, cap, std::ignore) = e;
 
                if(cap > 0 && level[w] < 0){
                    level[w] = level[v] + 1;
                    q.emplace(w);
                }
            }
        }
    }
 
    int dfs(int v, int t, int flow){
        if(v == t){
            return flow;
        }
 
        for(int i=lastIndex[v];i<(int)graph[v].size();++i){
            int w, rev;
            int &cap = std::get<1>(graph[v][i]);
            std::tie(w, std::ignore, rev) = graph[v][i];
            int &rev_cap = std::get<1>(graph[w][rev]);
             
            if(cap > 0 && level[w] > level[v]){
                int f = dfs(w, t, std::min(flow, cap));
                if(f > 0){
                    cap -= f;
                    rev_cap += f;
                    return f;
                }
            }
        }
 
        return 0;
    }
 
    int64_t solve(int s, int t){
        int64_t res = 0;
        while(true){
            bfs(s);
            if(level[t] < 0){
                return res;
            }
            std::fill(lastIndex.begin(), lastIndex.end(), 0);
            int f;
            while((f = dfs(s, t, std::numeric_limits<int>::max())) > 0){
                res += f;
            }
        }
         
        return 0;
    }
};

int main(){
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);

    std::cin >> H >> W;

    for(int i=0;i<H;++i){
        std::cin >> A[i];

        for(int j=0;j<W;++j){
            if(A[i][j] == 'S'){
                sy = i;
                sx = j;
            }else if(A[i][j] == 'T'){
                gy = i;
                gx = j;
            }
        }
    }

    // 0: 始点
    // 1: 終点
    // [2, H + 2): 行に対応する頂点
    // [H + 2, H + W + 2): 列に対応する頂点
    ResidualGraph g(H + W + 2);

    g.add(0, sy + 2, INF);
    g.add(0, sx + H + 2, INF);
    g.add(gy + 2, 1, INF);
    g.add(gx + H + 2, 1, INF);

    for(int i=0;i<H;++i){
        for(int j=0;j<W;++j){
            if(A[i][j] == 'o'){
                g.add(i + 2, j + H + 2, 1);
                g.add(j + H + 2, i + 2, 1);
            }
        }
    }

    Dinitz d(g);
    int mn = d.solve(0, 1);

    if(mn <= H * W){
        std::cout << mn << std::endl;
    }else{
        std::cout << -1 << std::endl;
    }
}


Measured memory_bytes: 896