#include <iostream>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <cassert>
#include <vector>
#include <list>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <string>
#include <algorithm>
#include <utility>
#define llint long long
//#define inf 1e18
#define rep(x, s, t) for(llint (x) = (s); (x) < (t); (x)++)
#define Rep(x, s, t) for(llint (x) = (s); (x) <= (t); (x)++)
#define chmin(x, y) (x) = min((x), (y))
#define chmax(x, y) (x) = max((x), (y))

using namespace std;
typedef pair<llint, llint> P;

#define inf 1e9


struct edge{
	int to, cap, cost, rev;
	edge(){}
	edge(int a, int b, int c, int d){
		to = a, cap = b, cost = c, rev = d;
	}
};

llint h, w;
char c[55][55];
vector<P> vec;
bool used[55][55];

int S, T;
vector<edge> G[4005];
int dist[4005];
int prevv[4005], preve[4005];

void BellmanFord()
{
	for(int i = 0; i <= T; i++) dist[i] = inf;
	dist[S] = 0, prevv[S] = -1;
	
	bool update = true;
	while(update){
		update = false;
		for(int i = 1; i <= T; i++){
			for(int j = 0; j < G[i].size(); j++){
				if(G[i][j].cap == 0) continue;
				if(dist[G[i][j].to] > dist[i] + G[i][j].cost){
					dist[G[i][j].to] = dist[i] + G[i][j].cost;
					prevv[G[i][j].to] = i;
					preve[G[i][j].to] = j;
					update = true;
				}
			}
		}
	}
}

void add_edge(int from, int to, int cap, int cost)
{
	G[from].push_back( edge(to, cap, cost, G[to].size()) );
	G[to].push_back( edge(from, 0, -cost, G[from].size()-1) );
}


int main(void)
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	cin >> h >> w;
	for(int y = 1; y <= h; y++){
		for(int x = 1; x <= w; x++){
			cin >> c[x][y];
		}
	}
	
	for(int y = 1; y <= h; y++){
		for(int x = 1; x <= w; x++){
			if(c[x][y] == 'o'){
				vec.push_back(P(x, y));
				c[x][y] = '.';
			}
		}
	}
	
	llint n = vec.size(), B = (h+1)*(w+1);
	S = B+n+1, T = B+n+2;
	for(int i = 0; i < vec.size(); i++){
		for(int y = 1; y <= h; y++){
			for(int x = 1; x <= w; x++){
				used[x][y] = false;
			}
		}
		int sx = vec[i].first, sy = vec[i].second;
		used[sx][sy] = true;
		for(int y = 1; y <= h; y++){
			for(int x = 1; x <= w; x++){
				if(!used[x][y]) continue;
				if(x+1 <= w && c[x+1][y] != '#') used[x+1][y] = true;
				if(y+1 <= h && c[x][y+1] != '#') used[x][y+1] = true;
			}
		}
		for(int y = 1; y <= h; y++){
			for(int x = 1; x <= w; x++){
				if(used[x][y]){
					add_edge(B+i, y*w+x, 1, -((x+y)-(sx+sy)));
				}
			}
		}
		add_edge(S, B+i, 1, 0);
	}
	for(int y = 1; y <= h; y++){
		for(int x = 1; x <= w; x++){
			add_edge(y*w+x, T, 1, 0);
		}
	}
	
	/*for(int i = 1; i <= T; i++){
		for(int j = 0; j < G[i].size(); j++){
			cout << i << " -> " << G[i][j].to << " " << G[i][j].cap << " " << G[i][j].cost << endl;
		}
	}*/
	
	
	int f = n, ans = 0;
	while(f > 0){
		//cout << f << " " << ans << endl;
		BellmanFord();
		if(dist[T] >= inf) break;
		
		int p = T, flow = f;
		while(prevv[p] != -1){
			flow = min(flow, G[prevv[p]][preve[p]].cap);
			p = prevv[p];
		}
		
		p = T;
		while(prevv[p] != -1){
			G[prevv[p]][preve[p]].cap -= flow;
			G[p][G[prevv[p]][preve[p]].rev].cap += flow;
			p = prevv[p];
		}
		f -= flow;
		ans += dist[T] * flow;
	}
	
	if(f > 0) ans = -1;
	cout << -ans << endl;
	
	return 0;
}

Measured memory_bytes: 6516