#include <bits/stdc++.h>

#define fi first
#define se second

const int N = 55;
const int mod = 1e9 + 7;

using namespace std;

typedef long long ll;
struct Edge{
    ll a,b,c,flow,cost;
};


const ll inf_ll = 1e18;
const int inf_int = 1e9;
#define pb push_back
const int MAXN = 1e4;

struct MIN_FLOW{
    vector<Edge> e;
    vector<int> g[MAXN];
    int n,s,t;

    int id[MAXN];
    ll dis[MAXN];
    int from[MAXN];
    void init(int N,int S,int T){
        n= N;
        s= S;
        t=T;
    }
    void add_edge(int a,int b,int c,ll cost){
        Edge e1 = {a,b,c,0,cost};
        Edge e2 = {b,a,0,0,-cost};
        g[a].pb(e.size());
        e.pb(e1);
        g[b].pb(e.size());;
        e.pb(e2);
    }

    ll get_val(int k){
        int flow = 0;
        ll cost = 0;

        while(1){
            queue<int> q;
            fill(id,id+n,0);
            fill(dis,dis+n,inf_ll);
            dis[s]=0;
            id[s]=1;
            q.push(s);
            while(!q.empty()){
                int v = q.front(); q.pop();
                id[v] = 0;
                for(int ind:g[v]){
                    Edge& edge = e[ind];
                    int to = edge.b;
                    if(edge.c >edge.flow && dis[edge.b] > dis[v] + edge.cost){
                        if(id[to] == 0){
                            q.push(to);
                            id[to] = 1;
                        }
                        dis[to] = dis[v] + edge.cost;
                        from[to] = ind;
                    }
                }

            }
            if(dis[t]==inf_ll)
                break;

            int addflow = min(inf_int,k-flow);
            int v = t;
            while(v!=s){
                int ind = from[v];
                addflow = min<ll>(addflow,e[ind].c - e[ind].flow);
                v = e[ind].a;
            }

            v = t;
            while(v!=s){
                int ind = from[v];
                cost += 1ll*e[ind].cost * addflow;
                e[ind].flow+=addflow;
                e[ind^1].flow-=addflow;
                v = e[ind].a;
            }
            flow+=addflow;
            if(flow==k)
                break;
        }

        return cost;
    }



} flow;

int n, m;
char a[N][N];

int main()
{
        ios_base::sync_with_stdio(0);

        //freopen("input.txt", "r", stdin);
        //freopen("output.txt", "w", stdout);

        cin >> n >> m;
        int O = 0;
        for(int i = 1; i <= n; i++){
                for(int j = 1; j <= m; j++){
                        cin >> a[i][j];
                        if(a[i][j] == 'o'){
                                O += 1;
                        }
                }
        }
        int cur = 0;
        int G = n * m;
        for(int i = 1; i <= n; i++){
                for(int j = 1; j <= m; j++){
                        if(a[i][j] != 'o'){
                                continue;
                        }
                        cur += 1;
                        queue < pair < int, int > > q;
                        vector < vector < int > > used(n + 1, vector < int > (m + 1, 0));
                        q.push({i, j});
                        used[i][j] = true;
                        while(!q.empty()){
                                int x = q.front().fi;
                                int y = q.front().se;
                                q.pop();
                                if((a[x + 1][y] == '.' || a[x + 1][y] == 'o') && !used[x + 1][y]){
                                        used[x + 1][y] = true;
                                        q.push({x + 1, y});
                                }
                                if((a[x][y + 1] == '.' || a[x][y + 1] == 'o') && !used[x][y + 1]){
                                        used[x][y + 1] = true;
                                        q.push({x, y + 1});
                                }
                        }
                        int st = i + j;
                        vector < pair < int, int > > g;
                        for(int i = 1; i <= n; i++){
                                for(int j = 1; j <= m; j++){
                                        if(used[i][j]){
                                                g.push_back({i + j - st, (i - 1) * m + j});
                                        }
                                }
                        }
                        sort(g.begin(), g.end());
                        reverse(g.begin(), g.end());
                        for(int i = 0; i < min(O, (int)g.size()); i++){
                                flow.add_edge(cur, O + g[i].se, 1, - g[i].fi);
                        }
                        flow.add_edge(0, cur, 1, 0);
                }
        }
        for(int i = 1; i <= G; i++){
                flow.add_edge(O + i, O + G + 1, 1, 0);
        }
        flow.init(O + G + 3, 0, O + G + 1);
        cout << - flow.get_val(O) << "\n";
}


Measured memory_bytes: 4964