#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 15
#define UNDEFINED 0
#define WHITE 1

struct Info{
	Info(int arg_row,int arg_col){
		row = arg_row;
		col = arg_col;
	}
	int row,col;
};

int H,W;
int diff_row[4] = {-1,0,0,1},diff_col[4] = {0,-1,1,0};
int boss[NUM],height[NUM];
bool check[NUM][NUM],FLG;
char table[NUM][NUM];
map<ll,int> dp[NUM][NUM];
vector<Info> G[NUM][NUM];


//自分のボスのindexを取得しつつ、経路圧縮を行う関数
int get_boss(int id){
	if(boss[id] == id)return id; //自分が代表なら、自分の値を返す
	else{
		return boss[id] = get_boss(boss[id]); //代表でないなら、自分が所属する組織の代表を返しつつ、経路圧縮
	}
}

int is_same(int x,int y){
	return get_boss(x) == get_boss(y);
}

void unite(int x,int y){
	int boss_x = get_boss(x);
	int boss_y = get_boss(y);

	//既に同じグループなら何もしない
	if(boss_x == boss_y)return;

	//高さが高い方に吸収する
	if(height[x] > height[y]){

		boss[boss_y] = boss_x;

	}else if(height[x] < height[y]){

		boss[boss_x] = boss_y;

	}else{ //height[x] == height[y]

		boss[boss_y] = boss_x;
		height[x]++;
	}
}


bool rangeCheck(int row,int col){

	return row >= 0 && row <= H-1 && col >= 0 && col <= W-1;
}

ll get_code(ll array[NUM]){

	ll ret = 0;

	for(int i = 0; i < W; i++){

		ret = 10*ret+array[i];
	}

	return ret;
}

bool is_ok(ll array[NUM]){

	//白マスが連続していないか調べる
	for(int col = 0; col < W-1; col++){

		if(array[col] == WHITE && array[col+1] == WHITE){

			return false;
		}
	}

	//任意の2つの黒セル間には1本だけ経路がある→グループは1つでなければならない
	for(int col = 0; col < W; col++){
		if(array[col] >= 3){

			return false;
		}
	}

	return true;
}

void rename(ll array[NUM]){

	ll check[100];

	for(int i = 0; i < 100; i++){

		check[i] = -1;
	}

	ll next_id = 2;

	for(int i = 0; i < W; i++){
		if(array[i] == UNDEFINED || array[i] == WHITE)continue;

		if(check[array[i]] == -1){
			check[array[i]] = next_id++;
		}
	}

	for(int i = 0; i < W; i++){
		if(array[i] == UNDEFINED || array[i] == WHITE)continue;
		array[i] = check[array[i]];
	}
}

int recursive(int row,int col,ll array[NUM],int last_group){

	if(row == H){

		if(is_ok(array)){

			return 0;

		}else{

			return -BIG_NUM;
		}
	}

	ll tmp_code = get_code(array);

	auto at = dp[row][col].find(tmp_code); //dpは、この状態から見て、これから未来に得られる最大値を持つ
	if(at != dp[row][col].end()){

		return dp[row][col][tmp_code];
	}

	int next_row,next_col,next_last_group = last_group;
	ll next_array[2][NUM];

	//次のrowとcolを設定
	if(col == W-1){

		next_row = row+1;
		next_col = 0;

	}else{

		next_row = row;
		next_col = col+1;
	}

	for(int i = 0; i < 2; i++){
		for(int a = 0; a < W; a++){
			next_array[i][a] = array[a];
		}
	}
	int ret = -BIG_NUM;

	//今回のマスを黒にする
	if(table[row][col] == '#' || table[row][col] == '?'){

		if(col > 0 && next_array[0][col-1] != WHITE && //左が黒
				next_array[0][col] != WHITE && next_array[0][col] != UNDEFINED && //上が黒
				next_array[0][col-1] == next_array[0][col]){ //左と右が同じグループ

			//Do nothing:閉路ができてしまうので黒で塗れない

		}else{

			if(col == 0 || next_array[0][col-1] == WHITE){ //左端、または左が白→左方に黒はない

				switch(next_array[0][col]){
				case UNDEFINED: //左にも上にも黒はない
				case WHITE:
					next_array[0][col] = next_last_group++; //新しいグループを作る
					break;
				default: //上のマスが黒
					//Do nothing:上のマスと同じグループにする
					break;
				}

				rename(next_array[0]);

				ret = max(ret,recursive(next_row,next_col,next_array[0],next_last_group)+1);

			}else{ //col >= 1 && array[col-1] == BLACK

				switch(next_array[0][col]){
				case UNDEFINED:
				case WHITE:
					next_array[0][col] = next_array[0][col-1]; //左のgroupと同じにする
					break;
				default: //上のマスが黒:上のマスと左のマスは異なるグループであるはず

					int new_id = next_array[0][col]; //★今回のマスの番号を新しいIDとして使用★
					int old_id = next_array[0][col-1];

					for(int a = 0; a < W; a++){ //同じIDが飛んで存在する場合あり
						if(next_array[0][a] == old_id){

							next_array[0][a] = new_id;
						}
					}

					break;
				}

				rename(next_array[0]);

				ret = max(ret,recursive(next_row,next_col,next_array[0],next_last_group)+1);

			}
		}
	}

	next_last_group = last_group;

	//今回のマスを白にする
	if(table[row][col] == '.' || table[row][col] == '?'){

		 if(next_array[1][col] == WHITE || (col > 0 && next_array[1][col-1] == WHITE)){ //上か左が白

			  //Do nothing:白が連続するので不可

		 }else{ //上にも左にも白はない

			 if(next_array[1][col] != UNDEFINED){ //上のマスが黒

				int count = 0;

				for(int a = 0; a < W; a++){
					if(next_array[1][a] == array[col]){
						count++;
					}
				}

				if(count == 1){
					//Do nothing:上のマスが孤立するので不可
				}else{

					//上のマスが黒で、左に白がない

					next_array[1][col] = WHITE;

					rename(next_array[1]);

					ret = max(ret,recursive(next_row,next_col,next_array[1],next_last_group));
				}

			 }else{

				 //上のマスがUNDFINEDで、左に白がない

				 next_array[1][col] = WHITE;

				 rename(next_array[1]);

				 ret = max(ret,recursive(next_row,next_col,next_array[1],next_last_group));
			 }
		 }
	}

	return dp[row][col][tmp_code] = ret;
}

void dfs(int row,int col,int pre_row,int pre_col){

	if(!FLG)return;

	int next_row,next_col;

	for(int i = 0; i < G[row][col].size(); i++){

		next_row = G[row][col][i].row;
		next_col = G[row][col][i].col;

		if(next_row == pre_row && next_col == pre_col)continue;

		if(check[next_row][next_col]){ //有向に遷移しているので、一度訪れた頂点をまた訪れたら閉路あり

			FLG = false;
			return;
		}
		check[next_row][next_col] = true;

		dfs(next_row,next_col,row,col);
	}
}


int main(){

	scanf("%d %d",&H,&W);

	for(int row = 0; row < H; row++){

		scanf("%s",table[row]);
	}

	//ややこしいので例外処理
	if(H == 1 || W == 1){

		if(H == 1 && W == 1){

			switch(table[0][0]){
			case '.':
				printf("0\n");
				break;
			case '#':
				printf("1\n");
				break;
			case '?':
				printf("1\n");
				break;
			}

			return 0;

		}else if(H == 1){

			//白ますが連続していたら不可
			for(int col = 0; col < W-1; col++){
				if(table[0][col] == '.' && table[0][col+1] == '.'){
					printf("-1\n");
					return 0;
				}
			}

			int ans = 0;

			//とりあえず?のところを前部黒にして、連結しているか調べる
			for(int col = 0; col < W; col++){
				if(table[0][col] == '?'){
					table[0][col] = '#';
					ans++;
				}else if(table[0][col] == '#'){
					ans++;
				}
			}

			for(int i = 0; i < W; i++){

				boss[i] = i;
				height[i] = 0;
			}

			for(int col = 0; col < W-1; col++){
				if(table[0][col] == '#' && table[0][col+1] == '#'){
					unite(col,col+1);
				}
			}

			int num_group = 0;

			for(int col = 0; col < W; col++){
				if(table[0][col] == '#'){
					if(get_boss(col) == col){
						num_group++;
					}
				}
			}

			if(num_group >= 2){

				printf("-1\n");

			}else{

				printf("%d\n",ans);
			}

			return 0;

		}else{ //W == 1


			//白ますが連続していたら不可
			for(int row = 0; row < H-1; row++){
				if(table[row][0] == '.' && table[row+1][0] == '.'){
					printf("-1\n");
					return 0;
				}
			}

			int ans = 0;

			//とりあえず?のところを前部黒にして、連結しているか調べる
			for(int row = 0; row < H; row++){
				if(table[row][0] == '?'){
					table[row][0] = '#';
					ans++;
				}else if(table[row][0] == '#'){
					ans++;
				}
			}

			for(int i = 0; i < H; i++){

				boss[i] = i;
				height[i] = 0;
			}

			for(int row = 0; row < H-1; row++){
				if(table[row][0] == '#' && table[row+1][0] == '#'){
					unite(row,row+1);
				}
			}

			int num_group = 0;

			for(int row = 0; row < H; row++){
				if(table[row][0] == '#'){
					if(get_boss(row) == row){
						num_group++;
					}
				}
			}

			if(num_group >= 2){

				printf("-1\n");

			}else{

				printf("%d\n",ans);
			}
			return 0;
		}
	}

	int adj_row,adj_col;

	//最初から閉路ができてないか調べる(dfsで調べるため、エッジを作る)
	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(table[row][col] != '#')continue;

			for(int i = 0; i < 4; i++){

				adj_row = row+diff_row[i];
				adj_col = col+diff_col[i];

				if(rangeCheck(adj_row,adj_col) == false || table[adj_row][adj_col] != '#')continue;

				G[row][col].push_back(Info(adj_row,adj_col));
			}
		}
	}

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(table[row][col] != '#')continue;

			for(int a = 0; a < H; a++){
				for(int b = 0; b < W; b++){
					check[a][b] = false;
				}
			}

			check[row][col] = true;
			FLG= true;

			dfs(row,col,-1,-1);

			if(!FLG){

				printf("-1\n");
				return 0;
			}
		}
	}

	ll first_array[NUM];

	for(int i = 0; i < W; i++){

		first_array[i] = UNDEFINED;
	}

	int ret = recursive(0,0,first_array,2);

	if(ret < 0){

		printf("-1\n");
	}else{

		printf("%d\n",ret);
	}

	return 0;
}



Measured memory_bytes: 21092