// Copyright (C) 2017 __debug.

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; version 3

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; If not, see <http://www.gnu.org/licenses/>.


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/priority_queue.hpp>

#define x first
#define y second
#define MP std::make_pair
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(), (x).end()
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#ifdef __linux__
#define getchar getchar_unlocked
#define putchar putchar_unlocked
#endif

using std::pair;
using std::vector;
using std::string;

typedef long long LL;
typedef pair<int, int> Pii;

const int oo = 0x3f3f3f3f;

template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, true : false; }
template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, true : false; }
string procStatus()
{
    std::ifstream t("/proc/self/status");
    return string(std::istreambuf_iterator<char>(t), std::istreambuf_iterator<char>());
}
template<typename T> T read(T &x)
{
    int f = 1;
    char ch = getchar();
    for (; !isdigit(ch); ch = getchar())
        f = (ch == '-' ? -1 : 1);
    for (x = 0; isdigit(ch); ch = getchar())
        x = 10 * x + ch - '0';
    return x *= f;
}
template<typename T> void write(T x)
{
    if (x == 0) {
        putchar('0');
        return;
    }
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    static char s[20];
    int top = 0;
    for (; x; x /= 10)
        s[++top] = x % 10 + '0';
    while (top)
        putchar(s[top--]);
}
// EOT

const int MAXW = 105;

int H, W;
char A[MAXW][MAXW];

void input()
{
    read(H); read(W);
    for (int i = 1; i <= H; ++i) {
        scanf("%s", A[i] + 1);
    }
}

namespace Dinic
{

const int MAXV = 3e4 + 5;
const int MAXE = 1e6 + 5;

struct Edge {
	int v, next;
	LL rsd;
	Edge() { }
	Edge(int v_, int next_, LL rsd_): v(v_), next(next_), rsd(rsd_) { }
};

int n, s, t;
int tote, head[MAXV];
Edge edge[MAXE];
int cur[MAXV];
int dis[MAXV];

inline void addEdge(int u, int v, LL cap)
{
	edge[++tote] = Edge(v, head[u], cap);
	head[u] = tote;
	edge[++tote] = Edge(u, head[v], 0);
	head[v] = tote;
}

bool bfs()
{
	static int q[MAXV];
	int front = 0, rear = 0;

	memset(dis + 1, +oo, sizeof(*dis) * n);
	dis[s] = 0;
	q[rear++] = s;
	while (front != rear) {
	    int u = q[front++];
	    for (int i = head[u]; i; i = edge[i].next) {
            const Edge &e = edge[i];
            if (e.rsd > 0 && dis[e.v] == +oo) {
                dis[e.v] = dis[u] + 1;
                q[rear++] = e.v;
            }
	    }
	}

	return dis[t] != +oo;
}

LL dfs(int u, LL rsd)
{
	if (u == t || !rsd) return rsd;
	LL ret = 0;
	for (int &i = cur[u]; i; i = edge[i].next) {
	    Edge &e = edge[i];
	    if (e.rsd > 0 && dis[u] + 1 == dis[e.v]) {
            LL f = dfs(e.v, rsd < e.rsd ? rsd : e.rsd);
            if (f > 0) {
                e.rsd -= f;
                edge[i ^ 1].rsd += f;
                rsd -= f;
                ret += f;
                if (!rsd) break;
            }
	    }
	}
	return ret;
}

inline void init(int n_)
{
	n = n_ + 2;
	s = n_ + 1;
	t = n_ + 2;
	tote = 1;
	memset(head + 1, 0, sizeof(*head) * n);
}

inline LL exec()
{
	LL ret = 0;
	while (bfs()) {
	    memcpy(cur + 1, head + 1, sizeof(*head) * n);
	    ret += dfs(s, +oo);
	}
	return ret;
}

}

#define IDX(i, j, k) ((((i) - 1) * W + (j)) * 2 - 1 + k)

void solve()
{
    int base = H * W * 2;
    Dinic::init(H * W * 2 + H + W);
    for (int i = 1; i <= H; ++i) {
        for (int j = 1; j <= W; ++j) {
            if (A[i][j] != '.') {
                Dinic::addEdge(IDX(i,j,1), IDX(i,j,0), 1);
                Dinic::addEdge(IDX(i,j,0), base+i, +oo);
                Dinic::addEdge(IDX(i,j,0), base+H+j, +oo);
                Dinic::addEdge(base+i, IDX(i,j,1), +oo);
                Dinic::addEdge(base+H+j, IDX(i,j,1), +oo);
                if (A[i][j] == 'S')
                    Dinic::addEdge(Dinic::s, IDX(i,j,0), +oo);
                else if (A[i][j] == 'T')
                    Dinic::addEdge(IDX(i,j,1), Dinic::t, +oo);
            }
        }
    }
    LL ans = Dinic::exec();
    if (ans >= +oo)
        ans = -1;
    printf("%lld\n", ans);
}

int main()
{
#ifdef __DEBUG
    freopen("F.in", "r", stdin);
    freopen("F.out", "w", stdout);
#endif

    input();
    solve();

    return 0;
}

// 读书不作儒生酸，跃马西入金城关。
//     -- 谢逸《送董元达》


Measured memory_bytes: 2176