#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif
//#pragma GCC optimize("O3")
#include <bits/stdc++.h>
using namespace std;
typedef long double ld;
typedef long long ll;
int h, w;
const int maxN = 105;
char c[maxN][maxN];
const int infinity = 1e9;
class DinitzFlow {
private:
    struct Edge {
        int src, dst, cap, flow;

        Edge() {
        }

        Edge(int src, int dst, int cap, int flow)
            : src(src), dst(dst), cap(cap), flow(flow) {
        }
    };

    int n, s, t;
    vector<Edge> edges;
    vector< vector<int> > g;
    vector<int> layer;
    vector<int> ptr;

    inline bool bfs() {
        layer.assign(n, -1);
        queue<int> q;
        layer[s] = 0;
        q.push(s);
        while (!q.empty() && layer[t] < 0) {
            int v = q.front(); q.pop();
            for (int eid: g[v]) {
                int to = edges[eid].dst;
                if (edges[eid].cap > edges[eid].flow) {
                    if (layer[to] < 0) {
                        layer[to] = layer[v] + 1;
                        q.push(to);
                    }
                }
            }
        }
        return layer[t] >= 0;
    }

    int dfs(int v, int flow = infinity) {
        if (v == t) {
            return flow;
        }
        if (flow == 0) {
            return 0;
        }
        for (; ptr[v] < (int)g[v].size(); ptr[v]++) {
            int eid = g[v][ptr[v]];
            int to = edges[eid].dst;
            if (layer[to] == layer[v] + 1) {
                int can = edges[eid].cap - edges[eid].flow;
                int pushed = dfs(to, min(flow, can));
                if (pushed > 0) {
                    edges[eid].flow += pushed;
                    edges[eid^1].flow -= pushed;
                    return pushed;
                }
            }
        }
        return 0;
    }
public:
    inline void changeSrcDst(int ns, int nt) {
        s = ns; t = nt;
        for (Edge &e : edges) {
            e.flow = 0;
        }
    }

    inline const vector<Edge> &getEdges() const {
        return edges;
    }

    inline vector<char> getCut() {
        // side[i] = 1 if the vertex is in component of s after the cut
        // side[i] = 0 otherwise (even if the vertex is not in component of t)
        vector<char> side(n, 0);

        function<void(int)> dfs = [&](int v) {
            if (side[v]) {
                return;
            }
            side[v] = 1;
            for (int eid : g[v]) {
                if (edges[eid].cap == edges[eid].flow) {
                    continue;
                }
                dfs(edges[eid].dst);
            }
        };

        dfs(s);
        return side;
    }

    inline int flow() {
        int ans = 0;
        while (bfs()) {
            ptr.assign(n, 0);
            int pushed = dfs(s);
            while (pushed != 0) {
                ans += pushed;
                pushed = dfs(s);
            }
        }
        return ans;
    }

    inline void addEdge(int src, int dst, int cap) {
        g[src].push_back(edges.size());
        edges.emplace_back(src, dst, cap, 0);
        g[dst].push_back(edges.size());
        edges.emplace_back(dst, src, 0, 0);
    }

    DinitzFlow(int n, int s, int t)
        : n(n), s(s), t(t), g(n), layer(n), ptr(n) {
    }
};
bool ok[maxN][maxN];
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
//    freopen("input.txt", "r", stdin);
    cin >> h >> w;
    int s = -1;
    int t = -1;
    for (int i = 1; i <= h; i++) {
        for (int j = 1; j <= w; j++) {
            cin >> c[i][j];
            if (c[i][j] == 'S') {
                s = (i - 1) * w + j;
                ok[i][j] = true;
            }
            if (c[i][j] == 'T') {
                t = (i - 1) * w + j;
                ok[i][j] = true;
            }
            if (c[i][j] == 'o') ok[i][j] = true;
        }
    }
    assert(s != -1 && t != -1);
    if (s % w == t % w || ((s - 1) / w == (t - 1) / w)) {
        cout << -1;
        return 0;
    }
    DinitzFlow ds(2 * h * w + 3, s + h * w, t);
    for (int i = 1; i <= h; i++) {
        for (int j = 1; j <= w; j++) {
            if (!ok[i][j]) continue;
            if (c[i][j] != 'S' && c[i][j] != 'T') {
                ds.addEdge((i - 1) * w + j, (i - 1) * w + j + h * w, 1);
            }
            for (int k = 1; k <= w; k++) {
                if (k == j) continue;
                if (!ok[i][k]) continue;
                int p = (i - 1) * w + j;
                int q = (i - 1) * w + k;
                if (c[i][k] == 'S') continue;
                if (c[i][j] == 'T') continue;
                ds.addEdge(p + h * w, q, 1);
            }
            for (int k = 1; k <= h; k++) {
                if (k == i) continue;
                if (!ok[k][j]) continue;
                int p = (i - 1) * w + j;
                int q = (k - 1) * w + j;
                if (c[i][j] == 'T') continue;
                if (c[k][j] == 'S') continue;
                ds.addEdge(p + h * w, q, 1);
            }
        }
    }
    cout << ds.flow() << '\n';
    return 0;
}

Measured memory_bytes: 85212