#include <bits/stdc++.h>
#define FOR(i, a, n) for(ll i = (ll)a; i < (ll)n; i++)
#define rep(i, n) FOR(i, 0, n)
#define ALL(x) (x).begin(), (x).end()
using namespace std;
typedef long long ll;

constexpr ll Mod = 998244353;
constexpr ll mod = 1e9 + 7;
constexpr ll inf = 1LL << 60;

template <typename T> constexpr bool chmax(T &a, const T b) {
    if(a >= b) return false;
    a = b;
    return true;
}
template <typename T> constexpr bool chmin(T &a, const T b) {
    if(a <= b) return false;
    a = b;
    return true;
}

/*-------------------------------------------*/

using FLOW = int;
const int MAX_V = 222;
const FLOW INF = 100000000;

// 辺
struct Edge {
    int rev, from, to;
    FLOW cap, icap;
    Edge(int r, int f, int t, FLOW c)
        : rev(r), from(f), to(t), cap(c), icap(c) {}
};

// グラフ
struct Graph {
    int V;
    vector<Edge> list[MAX_V];
    Graph(int n = 0) : V(n) { rep(i, MAX_V) list[i].clear(); }
    void init(int n = 0) {
        V = n;
        rep(i, MAX_V) list[i].clear();
    }
    void resize(int n = 0) { V = n; }
    void reset() {
        rep(i, V) rep(j, list[i].size()) list[i][j].cap = list[i][j].icap;
    }
    inline vector<Edge> &operator[](int i) { return list[i]; }
    Edge &redge(Edge e) {
        if(e.from != e.to) return list[e.to][e.rev];
        return list[e.to][e.rev + 1];
    }
    void addedge(int from, int to, FLOW cap) {
        list[from].push_back(Edge((int)list[to].size(), from, to, cap));
        list[to].push_back(Edge((int)list[from].size() - 1, to, from, 0));
    }
};

static int level[MAX_V];
static int iter[MAX_V];

void dibfs(Graph &G, int s) {
    rep(i, MAX_V) level[i] = -1;
    level[s] = 0;
    queue<int> que;
    que.push(s);
    while(!que.empty()) {
        int v = que.front();
        que.pop();
        for(Edge e : G[v]) {
            if(level[e.to] < 0 && e.cap > 0) {
                level[e.to] = level[v] + 1;
                que.push(e.to);
            }
        }
    }
}

FLOW didfs(Graph &G, int v, int t, FLOW f) {
    if(v == t) return f;
    for(int &i = iter[v]; i < G[v].size(); i++) {
        Edge &e = G[v][i], &re = G.redge(e);
        if(level[v] < level[e.to] && e.cap > 0) {
            FLOW d = didfs(G, e.to, t, min(f, e.cap));
            if(d > 0) {
                e.cap -= d;
                re.cap += d;
                return d;
            }
        }
    }
    return 0;
}

// 最大流
FLOW Dinic(Graph &G, int s, int t) {
    FLOW res = 0;
    while(true) {
        dibfs(G, s);
        if(level[t] < 0) return res;
        memset(iter, 0, sizeof(iter));
        FLOW flow;
        while(true) {
            flow = didfs(G, s, t, INF);
            if(flow <= 0) break;
            res += flow;
        }
    }
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(0);

    int h, w;
    cin >> h >> w;
    Graph G(h + w + 2);
    int S = h + w;
    int T = h + w + 1;

    rep(i, h) rep(j, w) {
        char c;
        cin >> c;
        if(c == 'S') {
            G.addedge(S, i, 100000);
            G.addedge(S, h + j, 100000);
        }
        if(c == 'T') {
            G.addedge(i, T, 100000);
            G.addedge(h + j, T, 100000);
        }
        if(c == 'o') {
            G.addedge(i, h + j, 1);
            G.addedge(h + j, i, 1);
        }
    }

    int ans = Dinic(G, S, T);
    cout << (ans < 1000 ? ans : -1) << endl;

    return 0;
}

Measured memory_bytes: 1280