#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <functional>
#include <cstring>
#include <string>
#include <map>
#include <set>
#include <iostream>
#include <ctime>
#include <complex>

#define enp 	printf("**Entry Point**\n")
#define A		first
#define B		second
#define MP		make_pair

using namespace std;

typedef long long ll;

const int INF = 0x6fffffff;
const int MINF = 0x80000000;
const ll mod = 100003;
const int cons = 100001;
const double pi = 3.141592653589793;


struct Network
{
	int n;

	struct edge
	{
		int to, rev, res;
	};

	vector < vector <edge> > adj;

	Network(int _n)
	{
		n = _n;
		adj.resize(n + 1);
	}

	void addEdge(int s, int e, int _cap, int _cap_rev = 0)
	{
		edge forward{ e, adj[e].size(), _cap };
		edge reverse{ s, adj[s].size(), _cap_rev };

		adj[s].push_back(forward);
		adj[e].push_back(reverse);
	}
};

struct Dinic
{
	int src, sink;
	int n;
	int maxFlow;
	vector <int> lev;
	vector <int> start;
	Network & N;

	Dinic(Network & _N, int _src, int _sink) :N(_N), src(_src), sink(_sink)
	{
		maxFlow = 0;
		n = N.n;
		lev.resize(n + 1);
		start.resize(n + 1);
		Start();
	}

	bool bfs()
	{
		for (int i = 0; i <= n; i++)lev[i] = 0;
		queue <int> qu;
		qu.push(src);
		lev[src] = 1;

		while (!qu.empty() && !lev[sink])
		{
			int u = qu.front();
			qu.pop();

			for (int i = 0; i < N.adj[u].size(); i++)
			{
				int v = N.adj[u][i].to;

				if (lev[v])continue;
				if (N.adj[u][i].res > 0)
				{
					lev[v] = lev[u] + 1;
					qu.push(v);
				}
			}
		}

		return lev[sink] != 0;
	}

	int dfs(int u, int flow)
	{
		if (u == sink)return flow;

		for (int & i = start[u]; i < N.adj[u].size(); i++)
		{
			int v = N.adj[u][i].to;

			if (lev[v] != lev[u] + 1)continue;
			if (N.adj[u][i].res <= 0)continue;

			if (int ret = dfs(v, min(flow, N.adj[u][i].res)))
			{
				N.adj[u][i].res -= ret;
				N.adj[v][N.adj[u][i].rev].res += ret;

				return ret;
			}
		}

		return 0;
	}

	void Start()
	{
		while (bfs())
		{
			for (int i = 0; i <= n; i++)start[i] = 0;
			while (int d = dfs(src, INF))maxFlow += d;
		}
	}
};

char M[102][102];
int r, c;
int dy[4] = { -1, 0, 1, 0 };
int dx[4] = { 0, -1, 0, 1 };

int getId(int y, int x)
{
	return y*c + x + 1;
}

int getOut(int in)
{
	return in + r*c;
}

int main()
{
	scanf("%d%d", &r, &c);

	int src = 0;
	int sink = 2*r*c + 1;

	Network N(sink);

	for (int i = 0; i < r; i++)
	{
		scanf("%s", M[i]);
		
		for (int j = 0; j < c; j++)
		{
			if (i == 0 || i == r - 1 || j == 0 || j == c - 1)
			{
				if (M[i][j] == 'X')
				{
					puts("-1");
					return 0;
				}

				N.addEdge(src, getId(i, j), 1);
			}
			else if(M[i][j] == 'X')
			{
				N.addEdge(getOut(getId(i, j)), sink, INF);
			}
		}
	}

	for (int i = 0; i < r; i++)
	{
		for (int j = 0; j < c; j++)
		{
			int uin = getId(i,j);
			int uout = getOut(uin);

			N.addEdge(uin, uout, M[i][j] == 'X' ? INF : 1);

			for (int k = 0; k < 4; k++)
			{
				int ty = i + dy[k];
				int tx = j + dx[k];

				if (ty < 0 || ty >= r || tx < 0 || tx >= c)continue;

				int vin = getId(ty, tx);
				int vout = getOut(vin);

				N.addEdge(uout, vin, 1);
			}
		}
	}

	Dinic D(N, src, sink);

	printf("%d\n", D.maxFlow);

	return 0;
}

Measured memory_bytes: 2944