#include <bits/stdc++.h>
#define st first
#define nd second

using namespace std;

void debug_out() { cerr << endl; }
template<class T> ostream& prnt(ostream& out, T v) { out << v.size() << '\n'; for(auto e : v) out << e << ' '; return out;}
template<class T> ostream& operator<<(ostream& out, vector <T> v) { return prnt(out, v); }
template<class T> ostream& operator<<(ostream& out, set <T> v) { return prnt(out, v); }
template<class T1, class T2> ostream& operator<<(ostream& out, map <T1, T2> v) { return prnt(out, v); }
template<class T1, class T2> ostream& operator<<(ostream& out, pair<T1, T2> p) { return out << '(' << p.st << ' ' << p.nd << ')'; }
template <typename Head, typename... Tail> void debug_out(Head H, Tail... T) { cerr << " " << H; debug_out(T...);}

#define dbg(...) cerr << #__VA_ARGS__ << " ->", debug_out(__VA_ARGS__)
#define dbg_v(x, n) do{cerr<<#x"[]: ";for(int _=0;_<n;++_)cerr<<x[_]<<" ";cerr<<'\n';}while(0)
#define dbg_ok cerr<<"OK!\n"

// const int N = ;
int n;

struct Dinic {
    struct Edge {
        int to, cap, flow, nxt;
    };
 
    vector<Edge> edges;
    vector<int> graph, at, dist;
    int src = 0, dest = 1;
 
    Dinic(int n, int m = 0) : graph(n, -1), dist(n, -1) {
        edges.reserve(2*m);
    }
 
    void m_add_edge(int from, int to, int cap) {
        edges.push_back(Edge {to, cap, 0, graph[from]});
        graph[from] = edges.size() - 1;
    }
    void add_edge(int from, int to, int cap) {
    	// dbg(from, to, cap);
        m_add_edge(from, to, cap);
        m_add_edge(to, from, 0);
    }
 
    void set_source_sink(int src, int dest) {
        this->src = src; this->dest = dest;
    }
 
    bool bfs(int step) {
        queue<int> q;
        fill(dist.begin(), dist.end(), -1);
        dist[src] = 0;
        q.push(src);
 
        while (!q.empty()) {
            int node = q.front(); q.pop();
            for (int i = graph[node]; i >= 0; i = edges[i].nxt) {
                const auto &e = edges[i];
                if (dist[e.to] == -1 && e.flow + step <= e.cap) {
                    dist[e.to] = dist[node] + 1;
                    q.push(e.to);
                }
            }
        }
 
        return dist[dest] != -1;
    }
 
    int dfs(int node, int flow) {
        if (flow == 0) return 0;
        if (node == dest) return flow;
 
        while (at[node] != -1) {
            int eid = at[node];
            const auto &e = edges[eid];
 
            if (dist[e.to] == dist[node] + 1) {
                if (int ret = dfs(e.to, min(flow, e.cap - e.flow))) {
                    edges[eid].flow += ret;
                    edges[eid^1].flow -= ret;
                    return ret;
                }
            }
 
            at[node] = e.nxt;
        }
 
        return 0;
    }
 
    int compute() {
        int ret = 0, step = (1 << 30);
 
        while (step > 0) {
            if (!bfs(step)) step /= 2;
            else {
                at = graph;
                while (int flow = dfs(src, step))
                    ret += flow;
            }
        }
 
        return ret;
    }
 
};
int m;
string s[111];

int main() {
	ios_base::sync_with_stdio(false);

	cin >> n >> m;
	Dinic dinic(n + m + 2);
	
	dinic.set_source_sink(0, n + m + 1);

	for(int i = 0; i < n; i++) {
		cin >> s[i];
		for(int j = 0; j < m; j++)
			if(s[i][j] == '.') 
				continue;
			else {

				if(s[i][j] == 'S') {
					dinic.add_edge(0, i + 1, 100000);
					dinic.add_edge(0, n + j + 1, 100000);
				} else if(s[i][j] == 'T') {
					dinic.add_edge(i + 1, n + m + 1, 100000);
					dinic.add_edge(n + j + 1, n + m + 1, 100000);
				} else {
					dinic.add_edge(i + 1, n + j + 1, 1);
					dinic.add_edge(n + j + 1, i + 1, 1);
					// dbg(i, j);
				}
			}
	}
	int r = dinic.compute();
	if(r > n * m) r = -1;
	cout << r << '\n';
}	

	

Measured memory_bytes: 1400