#include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class T>
using Table = vector<vector<T>>;
const ld eps=1e-9;

//// < "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\a.txt"


struct UnionFind {
	vector<int> data;
	UnionFind(int size) : data(size, -1) { }
	bool unionSet(int x, int y) {
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		return x != y;
	}
	bool findSet(int x, int y) {
		return root(x) == root(y);
	}
	int root(int x) {
		return data[x] < 0 ? x : data[x] = root(data[x]);
	}
	int size(int x) {
		return -data[root(x)];
	}
};


int main() {
	int H, W; cin >> H >> W;
	vector<vector<int>>field(H, vector<int>(W));
	for (int i = 0; i < H; ++i) {
		string st; cin >> st;
		for (int j = 0; j < W; ++j) {
			if (st[j] == '.') {
				field[i][j] = 0;
			}
			else if (st[j] == '#') {
				field[i][j] = 1;
			}
			else {
				field[i][j] = -1;
			}
		}
	}
	if (W == 1) {
		swap(H, W);
		vector<vector<int>>newfield(H, vector<int>(W));
		for (int i = 0; i < H; ++i) {
			for (int j = 0; j < W; ++j) {
				newfield[i][j] = field[j][i];
			}
		}
		field = newfield;
	}
	if (H == 1 && W == 1) {
		if (field[0][0] == 0) {
			cout << 0 << endl;
		}
		else {
			cout << 1 << endl;
		}
		return 0;
	}
	map<vector<int>,  int>mp;
	vector<int>start(W);
	iota(start.begin(), start.end(), 1);
	mp[start] = 0;
	int finans = -1;
	for (int y = 0; y < H; ++y) {
		map<vector<int>,int>newmp;
		for (int b = 0; b < (1 << W); ++b) {
			const bitset<11>bs(b);
			bool aaok = true;
			for (int x = 0; x < W - 1; ++x) {
				if (!bs[x] && !bs[x + 1])aaok = false;
			}
			for (int x = 0; x < W; ++x) {
				if (field[y][x] != -1) {
					if (field[y][x] != bs[x])aaok = false;
				}
			}
			if (!aaok)continue;
			for (const auto m : mp) {
				const vector<int>upbelongs(m.first);
				const int ans = m.second;
				bool ok = true;
				
				UnionFind uf(W);
				for (int l = 0; l < W; ++l) {
					for (int r = l + 1; r < W; ++r) {
						if (bs[l] && bs[r]) {
							if (upbelongs[l] && upbelongs[r]) {
								if (upbelongs[l] == upbelongs[r]) {
									uf.unionSet(l, r);
								}
							}
						}
					}
				}
				if (y) {
					for (int aa = 1; aa < 11; ++aa) {
						if (find(upbelongs.begin(), upbelongs.end(), aa) != upbelongs.end()) {
							bool aok = false;
							for (int x = 0; x < W; ++x) {
								if (upbelongs[x] == aa) {
									if (bs[x])aok = true;
								}
							}
							if (!aok)ok = false;
						}
					}
				}
					
				for (int x = 0; x < W-1; ++x) {
					if (bs[x]&&bs[x+1]) {
						if (uf.root(x) == uf.root(x + 1))ok = false;
						uf.unionSet(x, x + 1);
					}
				}
				for (int x = 0; x < W; ++x) {
					if (!bs[x] && !upbelongs[x])ok = false;
				}
				if (!ok)continue;
				else {
					map<int, int>amp;
					int anum = 1;
					vector<int>fins(W);
					for (int x = 0; x < W; ++x) {
						if (bs[x]) {
							if (amp.find(uf.root(x)) == amp.end()) {
								amp[uf.root(x)] = anum;
								anum++;
							}
							fins[x] = amp[uf.root(x)];
						}
					}
					newmp[fins] = max(newmp[fins],int(ans+bs.count()));
				}
				
			}
		}
		mp = newmp;
	}
	for (auto m : mp) {
		if (*max_element(m.first.begin(), m.first.end()) == 1) {
			finans = max(finans, m.second);
		}
	}
	if (!finans)finans = -1;
	cout << finans << endl;
	return 0;
}

Measured memory_bytes: 3772