//=================================
// Created on: 2018/09/22 02:07:55
//=================================
#include <bits/stdc++.h>
#define show(x) std::cerr << #x << " = " << x << std::endl
using ll = long long;
template <typename T>
constexpr T INF = std::numeric_limits<T>::max() / 10;
class Flow
{
public:
    using T = ll;
    struct Edge
    {
        std::size_t from, to, revind;
        T capacity, flow;
        bool reversed;
    };
    Flow(const std::size_t v) : V{v}, edge(v) {}
    void addEdge(const std::size_t from, const std::size_t to, const T capacity)
    {
        edge[from].push_back(Edge{from, to, (std::size_t)edge[to].size(), capacity, 0, false});
        edge[to].push_back(Edge{to, from, (std::size_t)edge[from].size() - 1, capacity, capacity, true});
    }
    T FordFulkerson(const std::size_t s, const std::size_t t)
    {
        std::vector<bool> checked(V);
        auto dfs = [&](auto&& self, const std::size_t pos, const T& flow) -> T {
            if (pos == t) { return flow; }
            checked[pos] = true;
            for (auto& e : edge[pos]) {
                if (checked[e.to]) { continue; }
                const T res = e.capacity - e.flow;
                if (res <= 0) { continue; }
                const T d = self(self, e.to, std::min(flow, res));
                if (d <= 0) { continue; }
                e.flow += std::min(d, res), edge[e.to][e.revind].flow -= std::min(d, res);
                return d;
            }
            return 0;
        };
        T flow = 0;
        while (true) {
            fill(checked.begin(), checked.end(), false);
            const T f = dfs(dfs, s, INF<T>);
            if (f == 0) { break; }
            flow += f;
        }
        return flow;
    }
    T Dinic(const std::size_t s, const std::size_t t)
    {
        T flow = 0;
        while (true) {
            std::vector<T> level(V, -1);
            auto dfs = [&](auto&& self, const std::size_t pos, const T& flow) -> T {
                if (pos == t) { return flow; }
                for (auto& e : edge[pos]) {
                    const T res = e.capacity - e.flow;
                    if (res <= 0 or level[pos] >= level[e.to]) { continue; }
                    const T d = self(self, e.to, std::min(flow, res));
                    if (d <= 0) { continue; }
                    e.flow += std::min(d, res), edge[e.to][e.revind].flow -= std::min(d, res);
                    return d;
                }
                return 0;
            };
            std::queue<std::size_t> q;
            q.push(s), level[s] = 0;
            while (not q.empty()) {
                const std::size_t v = q.front();
                for (const auto& e : edge[s]) {
                    if (e.capacity > e.flow and level[e.to] < 0) { level[e.to] = level[v] + 1, q.push(e.to); }
                }
            }
            while (true) {
                const T f = dfs(dfs, s, INF<T>);
                if (f == 0) { break; }
                flow += f;
            }
        }
    }
    const std::size_t V;
    std::vector<std::vector<Edge>> edge;
};

int main()
{
    int H, W;
    std::cin >> H >> W;
    Flow f(H + W + 2);
    const int S = H + W, T = H + W + 1;
    int sx, sy, tx, ty;
    for (int i = 0; i < H; i++) {
        std::string s;
        std::cin >> s;
        for (int j = 0; j < W; j++) {
            if (s[j] == 'o') { f.addEdge(i, j + H, 1), f.addEdge(j + H, i, 1); }
            if (s[j] == 'S') { sy = i, sx = H + j; }
            if (s[j] == 'T') { ty = i, tx = H + j; }
        }
    }
    if (sy == ty or sx == tx) { return std::cout << -1 << std::endl, 0; }
    f.addEdge(S, sy, INF<int>);
    f.addEdge(S, sx, INF<int>);
    f.addEdge(ty, T, INF<int>);
    f.addEdge(tx, T, INF<int>);
    const int F = f.FordFulkerson(S, T);
    std::cout << F << std::endl;
    return 0;
}


Measured memory_bytes: 2688