use std::io::*;
use std::str::FromStr;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

type Weight = i32;
#[allow(dead_code)]
#[derive(Clone, Debug, Eq, PartialEq)]
struct Edge {
    index: usize,
    src: usize,
    dest: usize,
    weight: Weight,
}
#[allow(dead_code)]
impl Edge {
    fn new(index: usize, src: usize, dest: usize, weight: Weight) -> Edge {
        Edge {
            index: index,
            src: src,
            dest: dest,
            weight: weight,
        }
    }
}
impl std::cmp::Ord for Edge {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        (self.weight, self.src, self.dest).cmp(&(other.weight, other.src, other.dest))
    }
}
impl std::cmp::PartialOrd for Edge {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}
type Edges = Vec<Edge>;
type Graph = Vec<Edges>;
#[allow(dead_code)]
fn graph_new(n: usize) -> Graph {
    vec![vec![]; n]
}
use std::collections::VecDeque;
// index ^ 1 is reverse edge
#[allow(dead_code)]
fn add_uni_edge(graph: &mut Graph, index: &mut usize, src: usize, dest: usize, weight: Weight) {
    graph[src].push(Edge::new(*index, src, dest, weight));
    *index += 1;
    graph[dest].push(Edge::new(*index, dest, src, 0));
    *index += 1;
}

#[allow(dead_code)]
fn augment(
    g: &Graph,
    capacity: &mut Vec<Weight>,
    level: &Vec<usize>,
    finished: &mut Vec<bool>,
    from: usize,
    t: usize,
    cur: Weight,
) -> Weight {
    if from == t || cur == 0 {
        return cur;
    }
    if finished[from] {
        return 0;
    }
    for edge in g[from].iter() {
        let to = edge.dest;
        if level[to] != level[from] + 1 {
            continue;
        }
        let ncur = std::cmp::min(cur, capacity[edge.index]);
        let f = augment(g, capacity, level, finished, to, t, ncur);
        if f > 0 {
            capacity[edge.index] -= f;
            capacity[edge.index ^ 1] += f;
            return f;
        }
    }
    finished[from] = true;
    0
}

#[allow(dead_code)]
fn max_flow(g: &Graph, e: usize, s: usize, t: usize) -> Weight {
    let n = g.len();
    let mut capacity: Vec<Weight> = vec![0; e];
    for from in 0..n {
        for edge in g[from].iter() {
            capacity[edge.index] += edge.weight;
        }
    }
    let mut ans = 0;
    loop {
        let mut level = vec![usize::max_value(); n];
        level[s] = 0;
        let mut que = VecDeque::<usize>::new();
        que.push_back(s);
        while let Some(from) = que.pop_front() {
            if from == t {
                break;
            }
            for edge in g[from].iter() {
                let to = edge.dest;
                if capacity[edge.index] > 0 && level[to] == usize::max_value() {
                    que.push_back(to);
                    level[to] = level[from] + 1;
                }
            }
        }
        let mut finished = vec![false; n];
        let mut end = true;
        loop {
            let f = augment(
                g,
                &mut capacity,
                &level,
                &mut finished,
                s,
                t,
                Weight::max_value(),
            );
            if f == 0 {
                break;
            }
            ans += f;
            end = false;
        }
        if end {
            break;
        }
    }
    ans
}

fn main() {
    let h = read::<usize>();
    let w = read::<usize>();
    let mut field = vec![vec![]; h];
    for y in 0..h {
        field[y] = read::<String>().chars().collect::<Vec<char>>();
    }
    let in_node = |y: usize, x: usize| y * w + x;
    let out_node = |y: usize, x: usize| y * w + x + h * w;
    let graph_size = || h * w * 2;
    let mut g = graph_new(graph_size());
    let mut e = 0;
    let mut s = 0;
    let mut t = 0;
    for y in 0..h {
        for x in 0..w {
            if field[y][x] == '.' {
                continue;
            }
            if field[y][x] == 'S' {
                s = in_node(y, x);
            }
            if field[y][x] == 'T' {
                t = out_node(y, x);
            }
            add_uni_edge(&mut g, &mut e, out_node(y, x), in_node(y, x), 1);
            for ny in 0..h {
                if y == ny || field[ny][x] == '.' {
                    continue;
                }
                add_uni_edge(&mut g, &mut e, in_node(y, x), out_node(ny, x), 1 << 20);
            }
            for nx in 0..w {
                if x == nx || field[y][nx] == '.' {
                    continue;
                }
                add_uni_edge(&mut g, &mut e, in_node(y, x), out_node(y, nx), 1 << 20);
            }
        }
    }
    let mut ans = max_flow(&g, e, s, t);
    if ans >= 1 << 20 {
        ans = -1;
    }
    println!("{}", ans);
}


Measured memory_bytes: 186620