#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
using namespace std;
typedef long long ll;
#define pb push_back
#define mii map <int, int>
#define mll map <ll, ll>
#define pii pair <int, int>
#define pll pair <ll, ll>
#define vi vector <int>
#define vd vector <double>
#define vll vector <ll>
#define fi first
#define se second
#define si set <int>
#define sll set <ll>
#define spii set <pii>
#define vs vector <string>
#define vpii vector <pair <int,int> >
#define vpll vector <pair <long long,long long> >
#define vvi vector <vector <int> >
#define vvpii vector <vector <pii > >
#define vb vector <bool>
#define vvb vector <vb>
#define mp make_pair
#define vvll vector <vll>
#define vsi vector <si>
#define rep(i, n) for (int i = 0; i < (n); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(),(x).rend()
#define MANX MAXN
#define itn int
#define in(x); { for (auto &to : x) cin>>to;}
#define out(x); { for (auto &to : x) cout<<to<<" ";cout<<'\n'; }
const ll  infl = 4e18 ;
const ll INFLL = 1e18;
const int MAXN = 1e6+100;
const ll INF = 1e9;
const ll mod1=1e9+7;
const ll mod2=2e9+11;
int nn,mm;
int n,m;
ll a[101][50*50+2];
#define rep(i,a,b) for (int i = (a); i <= (b); i++)
ll hungarian() { // Return the matching job->worker but in 1-indexing -> job[1] = 2
    vi mtch(m + 1) ; // mtch[i] = job assigned to person i in current matching
    vll u(n + 1) ;
    vll v(m + 1) ;
    vi way(m + 1) ;
    vi pre(m + 1) ;
    rep(i,1,n) { // Augment from i by finding an increasing chain - Kuhn
            vll dist(m + 1, INFLL) ;
            vb vis(m + 1, false) ;
            int cur_per = 0 ;
            mtch[cur_per] = i ;
            while(mtch[cur_per]) { // While there is an not an unsaturated person
                int cur_job = mtch[cur_per] ;
                vis[cur_per] = true ;
                ll delta = infl ;
                int nxt_per ;
                rep(j,1,m) {
                        if(!vis[j]) {
                            ll val = a[cur_job][j] - u[cur_job] - v[j] ;
                            if(val < dist[j]) {
                                dist[j] = val ;
                                way[j] = cur_per ;
                            }
                            if(dist[j] < delta) {
                                delta = dist[j] ;
                                nxt_per = j ;
                            }
                        }
                }
                rep(j,0,m) {
                        if(vis[j]) {
                            u[mtch[j]] += delta ;
                            v[j] -= delta ;
                        }
                        else {
                            dist[j] -= delta ;
                        }
                }
                cur_per = nxt_per ;
            }
            while(cur_per) { // Flip the matching
                int prev_per = way[cur_per] ;
                mtch[cur_per] = mtch[prev_per] ;
                cur_per = prev_per ;
            }
    }
    return -v[0];
}
int k=0;
vector <string> s;
int curr=1;
vector <int> x={1,0};
vector <int> y={0,1};
vector <vector <bool >> used;
void dfs(int i,int j,int ok)
{
   // cout<<i<<" "<<j<<" "<<nn*mm<<" "<<i*mm+j<<" "<<curr<<'\n';
    a[curr][i*mm+j+1]=-ok;
    used[i][j]=true;
    for (int f=0;f<2;f++)
    {
        if (i+x[f]<nn&&j+y[f]<mm&&s[i+x[f]][j+y[f]]!='#'&&!used[i+x[f]][j+y[f]])
        {
            dfs(i+x[f],j+y[f],ok+1);
        }
    }
}
void bfs(int i,int j)
{
    queue<pii> q;
    q.push({i,j});
    a[curr][i*mm+j+1]=0;
    while (!q.empty())
    {
        int xx=q.front().fi,yy=q.front().se;
        q.pop();
        for (int f=0;f<2;f++)
        {
            if (xx+x[f]<nn&&yy+y[f]<mm&&s[xx+x[f]][yy+y[f]]!='#'&&a[curr][(xx+x[f])*mm+yy+y[f]+1]==INF)
            {
                a[curr][(xx+x[f])*mm+yy+y[f]+1]=a[curr][xx*mm+yy+1]-1;
                //cout<<a[curr][xx*m+yy]-1<<'\n';
                q.push({xx+x[f],yy+y[f]});
            }
        }
    }
}

void solve()
{
    cin>>nn>>mm;
//    nn = 50;
//    mm = 50;
    s=vector <string>(nn);
    for (int i=0;i<nn;i++)
    cin>>s[i];
    for (int i=0;i<nn;i++)
    {
        for (int j=0;j<mm;j++)
            k+=s[i][j]=='o';
    }
    //cout<<k<<'\n';
    for (int i=0;i<=k;i++)
    {
        for (int f=0;f<=nn*mm;f++)
            a[i][f]=INF;
    }
    for (int i=0;i<nn;i++)
    {
        for (int j=0;j<mm;j++)
        {
            if (s[i][j]!='o')
                continue;
            bfs(i,j);
            curr++;
        }
    }
   // cout<<"ahha\n";
    n=k;
    m=nn*mm;
    cout<<-hungarian()<<'\n';

}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    #ifdef Mip182
    freopen("a.in","r",stdin);
    #endif
    int _t;
    _t=1;
 //   cin>>_t;
    while (_t--)
        solve();
    //n=1 ?
    //recursion - matrix exponential
    //linear algebra - just a joke
    //check ios_base, MAXN, mod1 before submit
    //if debug more than 15 minutes - write stress
    //compression
}

Measured memory_bytes: 5696