#include <bits/stdc++.h>
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
using namespace std;

typedef long long ll;
typedef unsigned long long llu;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef pair<int, pii> piii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<int, ll> pil;
typedef pair<string, int> psi;
typedef pair<char, int> pci;
typedef pair<int, char> pic;
const int MOD = 1e9 + 7;
const long double PI = 3.141592653589793238462643383279502884197;

ll fac[1] = {1}, inv[1] = {1};
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll mp(ll a,ll b){ll ret=1;while(b){if(b&1)ret=ret*a%MOD;a=a*a%MOD;b>>=1;}return ret;}
ll cmb(ll r, ll c) {return (c>r||c<0) ? 0:fac[r] * inv[c] % MOD * inv[r - c] % MOD;}

// 1. s + e + 50*50*2 만큼의 정점 플로우가 필요함.
// 2. 간선처리 + 용량처리 미리 다 구해놓고.
// 여기서 갈 수 있는 공간.
// 그리고... 모든 o들에서 dp 다 구하고..
// 그 과정에서 간선도 다 만들자.

const int s = 2500, e = 2501;

struct mcmf {
    struct edg {
        int v,c,f,cost;
        edg *op;
        edg() : edg(0,0,0,0) {}
        edg(int a, int b, int c, edg *d) : v(a), c(b), f(0), cost(c), op(d) {}
        void flow(int a) {
            f += a;
            op->f -= a;
        }
    };
    vector<edg*> v[e+1];
    int dist[e+1];
    edg *p[e+1];
    char visit[e+1];

    void init() {
        for (int i = 0; i <= e; i++) {
            for (int j = 0; j < sz(v[i]); j++)
                delete v[i][j];
            v[i].clear();
        }
    }
    void aed(int a, int b, int f, int c) {
        edg *q = new edg(b, f, c, 0), *w = new edg(a, 0, -c, 0);
        q->op = w, w->op = q;
        v[a].push_back(q);
        v[b].push_back(w);
    }
    int spfa() {
        fill(dist, dist+e+1, MOD);

        queue<int> q;
        q.push(s);
        dist[s] = 0;

        while (!q.empty()) {
            int tv = q.front();
            q.pop();
            visit[tv] = 0;

            for (auto i : v[tv]) {
                if (dist[i->v] > dist[tv] + i->cost && i->c - i->f) {
                    dist[i->v] = dist[tv] + i->cost;
                    p[i->v] = i;
                    if (!visit[i->v]) {
                        visit[i->v] = 1;
                        q.push(i->v);
                    }
                }
            }
        }
        return dist[e] != MOD;
    }
    pii cal() {
        pii ret = {0, 0};
        while (spfa()) {
            int f = MOD;
            for (int i = e; i != s; i = p[i]->op->v) f = min(f, p[i]->c - p[i]->f);

            ll t = 0;
            for (int i = e; i != s; i = p[i]->op->v) {
                p[i]->flow(f);
                t += p[i]->cost * f;
            }
            // if (t >= 0) break;

            ret.first += f;
            ret.second += t;
        }
        return ret;
    }
} mf;

int n, m;
char mat[50][51];

/*
void go(int x, int y) {
    if (visit[x][y]) return;
    visit[x][y] = 1;
    // printf("%d %d\n", x, y);
    if (x != n-1 && mat[x+1][y] != '#') {
        go(x+1, y);
    }
    if (y != m-1 && mat[x][y+1] != '#') {
        mf.aed(x*50+y, x*50+y+1, MOD, -1);
        go(x, y+1);
    }
}*/

// 저게 추후에 정해질 내용이다.
// 그냥 맥시멈 코스트 구하는거니까, 음수로 넣어야겠지?

int main() {
    scanf("%d %d", &n, &m);
    mf.init();
    for (int i = 0; i < n; i++) {
        scanf("%s", mat[i]);
        for (int j = 0; j < m; j++) {
            if (mat[i][j] != '#') mf.aed(i*50 + j, e, 1, 0);
            if (mat[i][j] == 'o') mf.aed(s,i*50+j,1,0);
        }
    }

    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++) {
            if (mat[i][j] == '#') continue;
            if (i != n-1 && mat[i+1][j] != '#') mf.aed(i*50+j, (i+1)*50+j, MOD, -1);
            if (j != m-1 && mat[i][j+1] != '#') mf.aed(i*50+j, i*50+j+1, MOD, -1);
        }

    /*
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++)
            printf("%d", visit[i][j]);
        printf("\n");
    }*/

    pii ret = mf.cal();
    printf("%d", -ret.second);
}


// author: rdd6584


Measured memory_bytes: 4468