#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <numeric>

#define REP(i, a, b) for (int i = int(a); i < int(b); i++)
using namespace std;
typedef long long int ll;

// clang-format off
#ifdef _DEBUG_
#define dump(...) do{ cerr << __LINE__ << ":\t" << #__VA_ARGS__ << " = "; PPPPP(__VA_ARGS__); cerr << endl; } while(false)
template<typename T> void PPPPP(T t) { cerr << t; }
template<typename T, typename... S> void PPPPP(T t, S... s) { cerr << t << ", "; PPPPP(s...); }
#else
#define dump(...)
#endif
template<typename T> vector<T> make_v(size_t a, T b) { return vector<T>(a, b); }
template<typename... Ts> auto make_v(size_t a, Ts... ts) { return vector<decltype(make_v(ts...))>(a, make_v(ts...)); }
template<typename T>
bool chmin(T &a, T b) { if (a > b) {a = b; return true; } return false;}
template<typename T>
bool chmax(T &a, T b) { if (a < b) {a = b; return true; } return false;}
// clang-format on

#include <queue>
template<typename T>
class Dinic {
    struct Edge {
        int to, rev;
        T cap;
        Edge(int t, int r, T c)
            : to(t), rev(r), cap(c) {}
    };
    int n;
    vector<vector<Edge>> G;
    vector<int> level;
    vector<int> itr;

    bool bfs(int s, int t) {
        queue<int> que;
        level.assign(n, -1);
        level[s] = 0;
        que.emplace(s);
        while (que.size()) {
            int v = que.front();
            que.pop();
            for (auto &edge : G[v]) {
                if (edge.cap > 0 && level[edge.to] == -1) {
                    level[edge.to] = level[v] + 1;
                    que.emplace(edge.to);
                }
            }
        }
        return level[t] != -1;
    }

    T dfs(int v, int t, T flow) {
        if (v == t) return flow;
        for (int &i = itr[v]; i < static_cast<int>(G[v].size()); i++) {
            auto &edge = G[v][i];
            if (edge.cap > 0 && level[v] < level[edge.to]) {
                T d = dfs(edge.to, t, min(flow, edge.cap));
                if (d > 0) {
                    edge.cap -= d;
                    G[edge.to][edge.rev].cap += d;
                    return d;
                }
            }
        }
        return 0;
    }

public:
    Dinic(int _n) {
        n = _n;
        G.resize(n);
    }
    void add_edge(int s, int t, T cap) {
        G[s].emplace_back(t, G[t].size(), cap);
        G[t].emplace_back(s, static_cast<int>(G[s].size() - 1), 0);
    }
    T max_flow(int s, int t, T inf) {
        T ans = 0;
        while (bfs(s, t)) {
            itr.assign(n, 0);
            for (T f = 0; (f = dfs(s, t, inf)) > 0; ans += f)
                ;
        }
        return ans;
    }
};

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int H, W;
    cin >> H >> W;
    auto mp = make_v(H, W, '.');
    int s = H + W, t = s + 1, n = t + 1;
    Dinic<ll> dinic(n);
    ll inf = 1LL << 60;
    REP(i, 0, H) {
        REP(j, 0, W) {
            cin >> mp[i][j];
            if (mp[i][j] == 'S') {
                dinic.add_edge(s, i, inf);
                dinic.add_edge(s, j + H, inf);
            } else if (mp[i][j] == 'T') {
                dinic.add_edge(i, t, inf);
                dinic.add_edge(j + H, t, inf);
            } else if (mp[i][j] == 'o') {
                dinic.add_edge(i, j + H, 1);
                dinic.add_edge(j + H, i, 1);
            }
        }
    }
    ll flow = dinic.max_flow(s, t, inf);
    if (flow >= inf) {
        flow = -1;
    }
    cout << flow << endl;
    return 0;
}


Measured memory_bytes: 1152