//#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define FIO ios_base::sync_with_stdio(false); cin.tie(0);
#define trav(x,a) for (auto& x: a)
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define mem(a,v) memset((a), (v), sizeof (a))
#define endl "\n"
#define case(t) cout << "Case #" << (t) << ": "
#define reada(a, n) for (int _i = 0; _i < (n); _i++) read(a[_i])
#define pii pair<int, int>
#define pll pair<long long, long long>
#define vii vector<pii>
#define vll vector<pll>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define mp make_pair
#define st first
#define nd second
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef cc_hash_table<int,int,hash<int>> ht;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> oset;
const double pi = acos(-1);
const int mod = 1e9 + 7;
const int inf = 1e9 + 7;
const int N = 1e6 + 5;
const double eps = 1e-9;

template<class T> void read(T& x) { cin >> x; }
template<class X, class Y> void read(pair<X,Y>& a) { read(a.first), read(a.second); }
template<class T> void read(vector<T>& x) { trav(y, x) read(y); }
template<class T, class... O> void read(T& x, O&... y) { read(x), read(y...); }

string to_string(const char& x) { return string(1,x); }
string to_string(const char*& x) { return (string)x; }
string to_string(const string& x) { return x; }
template<class T, class U> string to_string(const pair<T,U>& x) { return to_string(x.first) + " " + to_string(x.second); }
template<class T> string to_string(const vector<T>& x) { string ret = ""; bool f = 0; trav(y, x) ret += (!f ? "" : " ") + to_string(y), f = 1; return ret; }
void print() { cout << endl; }
template<class T> void pr(const T& x) { cout << to_string(x); }
template<class T, class... O> void print(const T& x, const O&... y) { pr(x); if (sizeof...(y)) pr(" "); print(y...); }

struct minBPM {
  vector<ll> mi, s, t;
  vector<int> mt, id, vis;
  int n, m;
  minBPM(int n, int m) : n(n),m(m),mi(m+1),s(m+1),t(n+1),mt(m+1),id(m+1),vis(m+1) {}
  ll matching(vector<vector<ll>> & mat) {
    for (int i = 1, x, nx, y; i <= n; i++) {
      fill(vis.begin(), vis.end(), 0);
      fill(mi.begin(), mi.end(), 1e18);
      mt[x=0] = i;
      do {
        vis[x] = 1, y = mt[x], nx = 0;
        ll d = 1e18;
        for (int j = 1; j <= m; j++) {
          if (vis[j]) continue;
          ll v = mat[y][j] - s[j] - t[y];
          mi[j] = v<mi[j] ? id[j]=x,v : mi[j];
          d = mi[j] < d ? nx=j, mi[j] : d;
        }
        for (int j = 0; j <= m; mi[j++] -= d)
          if (vis[j])
            s[j] -= d, t[mt[j]] += d;
      } while (mt[x = nx] != 0);
      for (;x!=0; mt[x]=mt[id[x]], x=id[x]);
    }
    return -s[0];
  }
};

vector<string> a;

int main() {
  FIO
  int n, m; read(n, m); a.resize(n); read(a);
  vector<vector<ll>> mat;
  {
    vector<ll> tmp(n*m+1, inf);
    mat.push_back(tmp);
  }
  int av = 0;
  for (int i = n-1; ~i; i--) {
    for (int j = m-1; ~j; j--) {
      if (a[i][j] != 'o')
        continue;
      int cnt = 0;
      if (i+1 < n && a[i+1][j] != '#')
        cnt++;
      if (j+1 < m && a[i][j+1] != '#')
        cnt++;
      if (cnt == 0) {
        a[i][j] = '#';
        continue;
      }
      av++;
      vector<int> vis(n*m, 0);
      deque<pii> pq;
      pq.push_back(mp(i, j));
      vector<ll> tmp(n*m+1, inf);
      while (sz(pq)) {
        pii cur = pq.front(); pq.pop_front();
        tmp[cur.st * m + cur.nd+1] = -(abs(i - cur.st) + abs(j - cur.nd));
        if (cur.st + 1 < n && a[cur.st+1][cur.nd] != '#' && vis[(cur.st+1) * m + cur.nd] == 0) {
          pq.push_back(mp(cur.st+1, cur.nd));
          vis[(cur.st+1)*m + cur.nd] = 1;
        }
        if (cur.nd + 1 < m && a[cur.st][cur.nd+1] != '#' && vis[cur.st * m + cur.nd+1] == 0) {
          pq.push_back(mp(cur.st, cur.nd+1));
          vis[cur.st*m + cur.nd+1] = 1;
        }
      }
      mat.push_back(tmp);
    }
  }
  // trav(x, a) print(x);
  // trav(x, mat) print(x);
  minBPM g(av, n*m);
  print(-g.matching(mat));
  return 0;
}


Measured memory_bytes: 5536