#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(auto i = (a); i < (b); i++)
#define pb push_back
#define fs first
#define sc second
typedef long long ll;
typedef pair<int,int> ii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ii> vii;
typedef vector<vii> vvii;

const double EPS = 1e-9;

char G[51][51];

vvii POS;

int n,m;
bool vis[51][51];
ii start;
void dfs(int i, int j) {
    if(i >= n || j >= m) return;
    if(G[i][j] == '#') return;
    if(vis[i][j]) return;
    POS[start.fs*m+start.sc].pb(ii(i,j));
    vis[i][j] = 1;
    dfs(i+1,j);
    dfs(i,j+1);
}


#define MAXV 5500
int d[MAXV], p[MAXV], pot[MAXV];
struct cmp { bool operator ()(int i, int j) const {
    return d[i] == d[j] ? i < j : d[i] < d[j]; } };

struct flow_network {
  struct edge { int v, nxt, cap, cost;
    edge(int _v, int _cap, int _cost, int _nxt)
      : v(_v), nxt(_nxt), cap(_cap), cost(_cost) { } };
  int n; vi head; vector<edge> e, e_store;
  flow_network(int _n) : n(_n), head(n,-1) { }
  void reset() { e = e_store; }
  void add_edge(int u, int v, int cost, int uv, int vu=0) {
    e.push_back(edge(v, uv, cost, head[u]));
    head[u] = (int)size(e)-1;
    e.push_back(edge(u, vu, -cost, head[v]));
    head[v] = (int)size(e)-1; }
  ii min_cost_max_flow(int s, int t, bool res=true) {
    e_store = e;
    memset(pot, 0, n*sizeof(int));
    rep(it,0,n-1) rep(i,0,size(e)) if (e[i].cap > 0)
      pot[e[i].v] =
        min(pot[e[i].v], pot[e[i^1].v] + e[i].cost);
    int v, f = 0, c = 0;
    while (true) {
      memset(d, -1, n*sizeof(int));
      memset(p, -1, n*sizeof(int));
      set<int, cmp> q;
      d[s] = 0; q.insert(s);
      while (!q.empty()) {
        int u = *q.begin();
        q.erase(q.begin());
        for (int i = head[u]; i != -1; i = e[i].nxt) {
          if (e[i].cap == 0) continue;
          int cd = d[u] + e[i].cost + pot[u] - pot[v = e[i].v];
          if (d[v] == -1 || cd < d[v]) {
            q.erase(v);
            d[v] = cd; p[v] = i;
            q.insert(v); } } }
      if (p[t] == -1) break;
      int at = p[t], x = INT_MAX;
      while (at != -1)
        x = min(x, e[at].cap), at = p[e[at^1].v];
      at = p[t], f += x;
      while (at != -1)
        e[at].cap -= x, e[at^1].cap += x, at = p[e[at^1].v];
      c += x * (d[t] + pot[t] - pot[s]);
      rep(i,0,n) if (p[i] != -1) pot[i] += d[i]; }
    if (res) reset();
    return ii(f, c); } };

int main() {
    cin.sync_with_stdio(false);
    cin >> n >> m;
    POS = vvii(n*m,vii());
    rep(i,0,n) rep(j,0,m) {
        cin >> G[i][j];
    }
    rep(i,0,n) rep(j,0,m) {
        if(G[i][j] == 'o') {
            memset(vis,0,sizeof(vis));
            start = ii(i,j);
            dfs(i,j);
        }
    }
    flow_network fn(n*m*2+50);
    int start = n*m*2+1;
    int end = n*m*2+2;
    rep(i,0,n) rep(j,0,m) {
        if(G[i][j] == 'o') {
            fn.add_edge(start, i*m+j, 0, 1);
            rep(z,0,POS[i*m+j].size()) {
                ii p = POS[i*m+j][z];
                int distance = abs(i-p.fs)+abs(j-p.sc);
                fn.add_edge(i*m+j, p.fs*m+p.sc+n*m, -distance, 1);
            }
        }
        if(G[i][j] != '#') {
            fn.add_edge(i*m+j+n*m, end, 0, 1);
        }
    }
    ii t = fn.min_cost_max_flow(start,end);
    cout << t.sc*-1 << endl;
}



Measured memory_bytes: 8424