#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define eb emplace_back
#define all(v) (v).begin(), (v).end() 
#define sz(v) (int)((v).size())
#define fs first
#define sd second

typedef long long ll;

typedef pair < int, int > pi;
typedef pair < pi, int > ppi;

typedef vector < int > vi;
typedef vector < vector < int > > vvi;
typedef vector < pi > vpi;
typedef vector < vpi > vvpi;
typedef vector < ppi > vppi;

void fast() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
}

vector<string> vec_splitter(string s) {
	s += ',';
	vector<string> res;
	while(!s.empty()) {
		res.push_back(s.substr(0, s.find(',')));
		s = s.substr(s.find(',') + 1);
	}
	return res;
}

void debug_out(
vector<string> __attribute__ ((unused)) args,
__attribute__ ((unused)) int idx, 
__attribute__ ((unused)) int LINE_NUM) { cerr << endl; } 
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, int LINE_NUM, Head H, Tail... T) {
	if(idx > 0) cerr << ", "; else cerr << "Line(" << LINE_NUM << ") ";
	stringstream ss; ss << H;
	cerr << args[idx] << " = " << ss.str();
	debug_out(args, idx + 1, LINE_NUM, T...);
}

#ifdef LOCAL
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __LINE__, __VA_ARGS__)
#else
#define debug(...) 42
#endif

double get_time() {
	return 1.0 * clock() / CLOCKS_PER_SEC;
}

struct Edge {
	int from, to, capacity, cost;
	Edge(int _from, int _to, int _capacity, int _cost) {
		from = _from;
		to = _to;
		capacity = _capacity;
		cost = _cost;
	}
};

const int INF = 1E9 + 5;

int n, m, N;
string s[55];
vector<Edge> edges;

void BFS(int sx, int sy, int id) {
	queue<pair<int, int>> q;
	q.push({sx, sy});
	vector<vector<int>> d(n, vector<int>(m)), vis(n, vector<int>(m));
	while(!q.empty()) {

		int x = q.front().fs, y = q.front().sd;
		// debug(x, y);
		q.pop();

		Edge e(2 + n * m + id, 2 + x * m + y, 1, d[x][y]);
		edges.push_back(e);

		if(x + 1 < n && !vis[x + 1][y] && s[x + 1][y] != '#') {
			vis[x + 1][y] = 1;
			d[x + 1][y] = d[x][y] + 1;
			q.push({x + 1, y});
		}
		if(y + 1 < m && !vis[x][y + 1] && s[x][y + 1] != '#') {
			vis[x][y + 1] = 1;
			d[x][y + 1] = d[x][y] + 1;
			q.push({x, y + 1});
		}
	}
}

void spfa(vector<vector<int>> &adj, vector<int> &p, vector<int> &d, vector<vector<int>> &capacity, vector<vector<int>> &cost, int s, int t) {
	debug(1);
	fill(d.begin(), d.end(), INF);
	queue<int> q;
	q.push(s);
	vector<int> in_queue(N);
	in_queue[s] = 1;
	d[s] = 0;

	while(!q.empty()) {
		int u = q.front();
		q.pop();
		in_queue[u] = 0;
		for(int v : adj[u]) {
			if(capacity[u][v] > 0 && d[u] + cost[u][v] < d[v]) {
				// in_queue[v] = 1;
				d[v] = d[u] + cost[u][v];
				p[v] = u;
				if(!in_queue[v]) {
					q.push(v);
					in_queue[v] = 1;
				}
			}
		}
	}

	debug(2);

	// if(d[t] == INF)
	// 	return 0;

	// int u = t;
	// int new_flow = INF;
	// while(u != s) {
	// 	new_flow = min(new_flow, cost[p[u]][u]);
	// 	u = p[u];
	// }

	// u = t;
	// while(u != s) {
	// 	capacity[p[u]][u] -= new_flow;
	// 	capacity[u][p[u]] += new_flow;
	// 	u = p[u];
	// }

	// return new_flow;
}

int min_cost_max_flow(int s = 0, int t = 1) {
	// debug(1);
	vector<int> p(N), d(N);
	vector<vector<int>> adj(N);
	vector<vector<int>> capacity(N, vector<int>(N)), cost(N, vector<int>(N));
	for(auto e : edges) {
		adj[e.from].push_back(e.to);
		adj[e.to].push_back(e.from);
		capacity[e.from][e.to] = e.capacity;
		cost[e.from][e.to] = -e.cost;
		cost[e.to][e.from] = e.cost;
	}

	// int new_flow;
	// cout << "YES" << '\n';
	int flow = 0, res = 0;
	// while(new_flow = spfa(adj, p, d, capacity, cost, s, t)) {
	// 	flow += new_flow;
	// 	res += d[t] * new_flow;
	// }

	while(true) {
		
		spfa(adj, p, d, capacity, cost, s, t);
		int del = INF;
		int u = t;
		while(u != s) {
			del = min(del, capacity[p[u]][u]);
			u = p[u];
		}

		if(d[t] == INF)
			break;

		flow += del;
		res += del * d[t];
		u = t;

		while(u != s) {
			capacity[p[u]][u] -= del;
			capacity[u][p[u]] += del;
			u = p[u];
		}
	}

	return res;
}

int main() {
	// int n, m;
	// string s[n];
	cin >> n >> m;
	// for(int i = 0; i < n; i++)
	// 	cin >> s[i];

	vector<pair<int, int>> pieces;
	for(int i = 0; i < n; i++) {
		cin >> s[i];
		for(int j = 0; j < m; j++)
			if(s[i][j] == 'o')
				pieces.push_back({i, j});
	}

	// debug(1);

	for(int i = 0; i < (int) pieces.size(); i++) {
		int x = pieces[i].fs, y = pieces[i].sd;
		// debug(x, y);
		BFS(x, y, i);
	}

	// for(auto e : edges) {
	// 	cout << e.from << ' ' << e.to << ' ' << e.capacity << ' ' << e.cost << '\n';
	// }

	for(int i = 0; i < n; i++) {
		for(int j = 0; j < m; j++) {
			// Edge e(0, 2 + m * i + j, 1, 0);
			// edges.push_back(e);
			Edge ee(2 + m * i + j, 1, 1, 0);
			edges.push_back(ee);
		}
	}

	for(int i = 0; i < (int) pieces.size(); i++) {
		Edge e(0, 2 + n * m + i, 1, 0);
		edges.push_back(e);
	}

	N = n * m + 2 + (int) pieces.size();
	cout << -min_cost_max_flow() << '\n';
}


Measured memory_bytes: 58316