/*
ID: espr1t
TASK: 
KEYWORDS: 
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>

using namespace std;
FILE* in = stdin; FILE* out = stdout;

const int MAX = 55;
const int INF = 1000000001;

int n, m;
char a[MAX][MAX];
int id[MAX][MAX];
bool vis[MAX][MAX];
vector < vector <long long> > mat;

/*
 * Implementation of Hungarian Algorithm in O(N * M * M)
 * Original code taken from https://gist.github.com/pathikrit/bc09b720f476c79a3553#file-library-java-L1396
 *
 * a[i][j] = amount bidder j is willing to pay for item i (0 if he is not bidding)
 * returns the best total price
 * in the end match[i] = j means item i was given to bidder j (or -1, if none)
 * for minimizing set matrix[i][j] = max(matrix) - matrix[i][j]
 * for assigning all, matrix[i][j] = min(matrix) + matrix[i][j]
 */

int match[MAX * MAX];

long long hungarianAlgorithm() {
    const int PHI = -1;
    const int NOL = -2;
    int n = (int)mat.size();
    int m = (int)mat[0].size();

    vector < vector <bool> > x(n, vector <bool>(m, false));
    vector <bool> ss(n, false), st(m, false);
    vector <int> u(n, 0), v(m, 0), p(m, 0), ls(n, 0), lt(m, 0);

    vector < vector <long long> > matrix = mat;
//    for (int row = 0; row < (int)matrix.size(); row++)
//        for (int col = 0; col < (int)matrix[row].size(); col++)
//            matrix[row][col] = -matrix[row][col];

    // Fix the matrix to contain only non-negative numbers
    long long minValue = 0;
    for (int row = 0; row < n; row++)
        minValue = min(minValue, *min_element(matrix[row].begin(), matrix[row].end()));
    for (int row = 0; row < n; row++)
        for (int col = 0; col < m; col++)
            matrix[row][col] -= minValue;

    long long maxValue = 0;
    for (int row = 0; row < n; row++)
        maxValue = max(maxValue, *max_element(matrix[row].begin(), matrix[row].end()));

    fill(u.begin(), u.end(), maxValue);
    fill(p.begin(), p.end(), INF);
    fill(lt.begin(), lt.end(), NOL);
    fill(ls.begin(), ls.end(), PHI);

    while (true) {
        int chosenRow = -1;
        for (int row = 0; row < n; row++)
            if (ls[row] != NOL && !ss[row])
                {chosenRow = row; break;}

        if (chosenRow != -1) {
            ss[chosenRow] = true;
            for (int col = 0; col < m; col++)
                if (!x[chosenRow][col] && u[chosenRow] + v[col] - matrix[chosenRow][col] < p[col]) {
                    lt[col] = chosenRow;
                    p[col] = u[chosenRow] + v[col] - matrix[chosenRow][col];
                }
        } else {
            int chosenCol = -1;
            for (int col = 0; col < m; col++)
                if (lt[col] != NOL && !st[col] && p[col] == 0)
                    {chosenCol = col; break;}

            if (chosenCol == -1) {
                int d1 = INF, d2 = INF, d;
                for (int i : u)
                    d1 = min(d1, i);

                for (int i : p)
                    if (i > 0)
                        d2 = min(d2, i);

                d = min(d1, d2);

                for (int row = 0; row < n; row++)
                    if (ls[row] != NOL)
                        u[row] -= d;

                for (int col = 0; col < m; col++) {
                    if (p[col] == 0)
                        v[col] += d;
                    if (p[col] > 0 && lt[col] != NOL)
                        p[col] -= d;
                }

                if (d2 >= d1)
                    break;
            } else {
                st[chosenCol] = true;
                chosenRow = -1;

                for (int row = 0; row < n; row++)
                    if (x[row][chosenCol])
                        {chosenRow = row; break;}

                if (chosenRow == -1) {
                    for (int l, r; ; chosenCol = r) {
                        r = chosenCol;

                        l = lt[r];
                        if (r < 0 || l < 0)
                            break;
                        x[l][r] = !x[l][r];

                        r = ls[l];
                        if (r < 0 || l < 0)
                            break;
                        x[l][r] = !x[l][r];
                    }

                    fill(p.begin(), p.end(), INF);
                    fill(lt.begin(), lt.end(), NOL);
                    fill(ls.begin(), ls.end(), NOL);
                    fill(ss.begin(), ss.end(), false);
                    fill(st.begin(), st.end(), false);

                    for (int row = 0; row < n; row++) {
                        bool flag = true;
                        for (int col = 0; col < m; col++)
                            if (x[row][col]) {flag = false; break;}
                        if (flag)
                            ls[row] = PHI;
                    }
                } else
                    ls[chosenRow] = chosenCol;
            }
        }
    }

    long long totalValue = 0;
    fill(match, match + n, -1);
    for (int row = 0; row < n; row++) {
        for (int col = 0; col < m; col++) {
            if (x[row][col]) {
                match[row] = col;
                totalValue += mat[row][col];
            }
        }
    }
    return totalValue;
}

void recurse(int row, int col, int steps) {
    if (vis[row][col])
        return;
    vis[row][col] = true;
    mat.back()[id[row][col]] = steps;
    if (row + 1 < n && a[row + 1][col] != '#')
        recurse(row + 1, col, steps + 1);
    if (col + 1 < m && a[row][col + 1] != '#')
        recurse(row, col + 1, steps + 1);
}

int solve() {
    int nextEmpty = 0;
    for (int row = 0; row < n; row++) {
        for (int col = 0; col < m; col++) {
            if (a[row][col] != '#') {
                id[row][col] = nextEmpty++;
            }
        }
    }
    
    for (int row = 0; row < n; row++) {
        for (int col = 0; col < m; col++) {
            if (a[row][col] == 'o') {
                mat.push_back(vector<long long>(nextEmpty, -INF));
                memset(vis, 0, sizeof(vis));
                recurse(row, col, 0);
            }
        }
    }
//    for (int i = 0; i < (int)mat.size(); i++)
//        for (int c = 0; c < (int)mat[i].size(); c++)
//            fprintf(stderr, "%lld%c", mat[i][c], c + 1 == (int)mat[i].size() ? '\n' : ' ');
    
    return hungarianAlgorithm();
}

int main(void) {
	// in = fopen("C.in", "rt");
	
	fscanf(in, "%d %d", &n, &m);
	for (int row = 0; row < n; row++)
	    fscanf(in, "%s", a[row]);
	fprintf(out, "%d\n", solve());
	
	return 0;
}

Measured memory_bytes: 6640