#include <stdio.h>
#include <stdlib.h>

#include <iostream>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <stdint.h>
#include <string.h>

#define _USE_MATH_DEFINES
#include <math.h>

#include <vector>
#include <list>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <stack>
#include <deque>
#include <string>

#include <algorithm>
#include <functional>
#include <bitset>
#include <functional>
#include <chrono>
#include <random>

#define sqr(x) (x) * (x)

typedef unsigned int u32;
typedef int i32;
typedef unsigned long long int u64;
typedef int i64;
typedef uint16_t u16;
typedef int16_t i16;
typedef uint8_t u8;
typedef int8_t i8;

using namespace std;
using namespace std::chrono;

const i64 mod = 1'000'000'000ll + 7;
// const i64 smod = 998'244'353ll;

const i64 inf = mod;

const long double eps = 1e-8;

i64 n, m;

i64 nx, mx;
vector<string> ax;

vector<pair<i64, i64>> o;

vector<vector<i16>> a;

int main(int argc, char* argv[]) {
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cout.precision(15); cout.setf(ios::fixed); cerr.precision(15); cerr.setf(ios::fixed);

    cin >> nx >> mx;
    ax = vector<string>(nx);
    for (i64 i = 0; i < nx; i++) {
        cin >> ax[i];
    }

    for (i64 i = 0; i < nx; i++) {
        for (i64 j = 0; j < mx; j++) {
            if (ax[i][j] == 'o') {
                o.push_back({ i, j });
            }
        }
    }

    n = o.size();
    m = nx * mx;

    a = vector<vector<i16>>(n + 1, vector<i16>(m + 1, 10'500));

    for (i64 i = 0; i < n; i++) {
        vector<pair<i64, i64>> q;
        set<pair<i64, i64>> used;

        q.push_back(o[i]);
        used.insert(o[i]);

        i64 len = q.size();
        i64 ans = 0;

        for (i64 k = 0; k < q.size(); k++) {
            if (len == k) {
                ans += 1;
                len = q.size();
            }

            i64 x = q[k].first;
            i64 y = q[k].second;

            a[1 + i][1 + x * mx + y] = -ans;

            if (x + 1 < nx && ax[x + 1][y] != '#' && !used.count({ x, y + 1 })) {
                q.push_back({ x + 1, y });
                used.insert({ x + 1, y });
            }

            if (y + 1 < mx && ax[x][y + 1] != '#' && !used.count({ x, y + 1 })) {
                q.push_back({ x, y + 1});
                used.insert({ x, y + 1 });
            }
        }
    }


    vector<i64> u(n + 1), v(m + 1), p(m + 1), way(m + 1);
    for (i64 i = 1; i <= n; ++i) {
        p[0] = i;
        i64 j0 = 0;
        vector<i64> minv(m + 1, inf);
        vector<char> used(m + 1, false);
        do {
            used[j0] = true;
            i64 i0 = p[j0], delta = inf, j1;
            for (i64 j = 1; j <= m; ++j)
                if (!used[j]) {
                    i64 cur = (a[i0][j] == 10'500 ? inf : (i64)a[i0][j]) - u[i0] - v[j];
                    if (cur < minv[j])
                        minv[j] = cur, way[j] = j0;
                    if (minv[j] < delta)
                        delta = minv[j], j1 = j;
                }
            for (i64 j = 0; j <= m; ++j)
                if (used[j])
                    u[p[j]] += delta, v[j] -= delta;
                else
                    minv[j] -= delta;
            j0 = j1;
        } while (p[j0] != 0);
        do {
            i64 j1 = way[j0];
            p[j0] = p[j1];
            j0 = j1;
        } while (j0);
    }

    cout << v[0] << endl;

    return 0;
}

Measured memory_bytes: 4308