#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<string>
#include<stack>
#include<cstdio>
#include<cmath>
using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> P;
typedef pair<int,P> P1;

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define rep(i,x) for(int i=0;i<x;i++)
#define rep1(i,x) for(int i=1;i<=x;i++)
#define rrep(i,x) for(int i=x-1;i>=0;i--)
#define rrep1(i,x) for(int i=x;i>0;i--)
#define sor(v) sort(v.begin(),v.end())
#define rev(s) reverse(s.begin(),s.end())
#define lb(vec,a) lower_bound(vec.begin(),vec.end(),a)
#define ub(vec,a) upper_bound(vec.begin(),vec.end(),a)
#define uniq(vec) vec.erase(unique(vec.begin(),vec.end()),vec.end())
#define mp1(a,b,c) P1(a,P(b,c))

const int INF=1000000000;
const int dir_4[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
const int dir_8[8][2]={{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};

const int MAX_V = 12;
struct UF{
	int par[MAX_V] , r[MAX_V];
	void init(){
		rep(i,MAX_V){
			par[i] = i;
			r[i] = 0;
		}
	}
	int find(int x){
		if(x == par[x])return x;
		return par[x] = find(par[x]);
	}
	bool same(int x,int y){
		return find(x) == find(y);
	}
	void unit(int x,int y){
		if(same(x,y))return;
		x=find(x);
		y=find(y);
		if(r[x]<r[y]){
			par[x]=y;
		}
		else {
			par[y]=x;
			if(r[x]==r[y]){
				r[x]++;
			}
		}
	}
	bool operator<(UF y) {
		rep(i,MAX_V){
			rep(j,MAX_V){
				if(y.same(i,j)){
					if(!this->same(i,j))return false;
				}
				else {
					if(this->same(i,j))return true;
				}
			}
		}
		return false;
	}
	bool operator==(UF y) {
		rep(i,MAX_V){
			rep(j,MAX_V){
				if(y.same(i,j)){
					if(!this->same(i,j))return false;
				}
				else {
					if(this->same(i,j))return false;
				}
			}
		}
		return true;
	}
};
UF uf;

int h,w;
struct A{
	bool black[12];
	UF uf;
	bool operator<(A y) const {
		rep(i,w){
			if(y.black[i] && (!this->black[i]))return true;
			if((!y.black[i]) && this->black[i])return false;
		}
		return y.uf < this->uf;
	}
	bool operator==(A y) const {
		rep(i,w){
			if(y.black[i] && (!this->black[i]))return false;
			if((!y.black[i]) && this->black[i])return false;
		}
		return y.uf == this->uf;
	}
};

int main(){
	static map<A,P> id;
	static A abcde[6000];
	static int cnt_abcde = 0;
	static A id_[6000];
	static int memo[6000];
	scanf("%d%d",&h,&w);
	
	rep(i,(1<<w)){
		A a;
		a.uf.init();
		int cnt = 0,cnt_ = 0,loc[6];
		rep(j,w)a.black[j] = (((i>>j)&1) == 1);
		rep(j,w-1)if((!a.black[j]) && (!a.black[j+1]))goto Next;
		rep(j,w){
			if(( j == 0 && a.black[0]) ||((!a.black[j-1]) && a.black[j])){
				loc[cnt++] = j;
			}
			if(a.black[j])cnt_ ++;
		}
		rep(k,w-1)if(a.black[k] && a.black[k+1])a.uf.unit(k,k+1);
		abcde[cnt_abcde++] = a;
		rep(j,(1<<((cnt*(cnt-1)))/2)){
			a.uf.init();
			rep(k,w-1)if(a.black[k] && a.black[k+1])a.uf.unit(k,k+1);
			int k = 0;
			rep(x,cnt){
				for(int y = x+1 ; y < cnt ; y ++){
					if((j>>k)&1)a.uf.unit(loc[x],loc[y]);
					k ++;
				}
			}
			if(id.find(a) == id.end()){
				id_[id.size()] = a;
				memo[id.size()] = cnt_;
				id[a] = P( id.size() , cnt_ );
			}
		}
		Next:;
	}
	
	int s = id.size();
	
	char c[12][12];
	rep(i,h){
		scanf("\n");
		rep(j,w){
			scanf("%c",&c[i][j]);
		}
	}
	
	int dp[2][6000];
	int pre[12][6000];
	int t = 0 , t_ = 1;
	rep(i,6000)dp[0][i] = -INF;
	rep(i,s){
		rep(j,w){
			if(c[0][j] == '#' && (!id_[i].black[j]))goto Next1;
			if(c[0][j] == '.' && id_[i].black[j])goto Next1;
		}
		rep(j,w){
			bool tt = false;
			for(int k = j+1 ; k < w ; k ++){
				if(!id_[i].black[k])tt = true;
				if(tt && id_[i].uf.same(j,k))goto Next1;
			}
		}
		dp[0][i] = memo[i];
		Next1:;
	}
	rep(x,h-1){
		rep(i,6000)dp[t_][i] = -INF;
		rep(i,s){
			if(dp[t][i] == -INF)continue;
			rep(ppp,cnt_abcde){
				A a = abcde[ppp],cop = id_[i];
				bool used[12];
				rep(j,w)if((!a.black[j]) && (!id_[i].black[j]))goto Next3;
				rep(j,w){
					if(c[x+1][j] == '#' && (!a.black[j]))goto Next3;
					if(c[x+1][j] == '.' && a.black[j])goto Next3;
				}
				uf.init();
				rep(j,w)used[j] = false;
				rep(j,w){
					if(a.black[j] && id_[i].black[j] && !used[a.uf.find(j)]){
						for(int k = j+1 ; k < w ; k ++){
							if(a.black[k]){
								if(a.uf.same(j,k)){
									if(uf.same(id_[i].uf.find(j),id_[i].uf.find(k)))goto Next3;
									else uf.unit(id_[i].uf.find(j),id_[i].uf.find(k));
								}
							}
							else break;
						}
						used[a.uf.find(j)] = true;
					}
				}
				rep(j,w){
					if(a.black[j] && id_[i].black[j]){
						for(int k = j+1 ; k < w ; k ++)if(a.black[k] && id_[i].black[k]){
							if(id_[i].uf.same(j,k))a.uf.unit(j,k);
						}
					}
				}
				if(!(w == 1 && x == h-2)){
					rep(j,w)if(a.black[j] && cop.black[j])cop.uf.unit(j,11);
					rep(j,w)if(cop.black[j] && (!cop.uf.same(j,11)))goto Next3;
				}
				
				dp[t_][id[a].fr] = max ( dp[t_][id[a].fr] , dp[t][i] + id[a].sc );
				Next3:;
			}
		}
		swap(t,t_);
	}
	
	int ret = -1;
	rep(i,s){
		if(dp[t][i] == -INF)continue;
		rep(j,w)for(int k = j+1 ; k < w ; k ++){
			if(id_[i].black[j] && id_[i].black[k] && (!id_[i].uf.same(j,k)))goto Next4;
		}
		ret = max ( ret , dp[t][i] );
		Next4:;
	}
	cout << ret << endl;
}

Measured memory_bytes: 2160