#include <iostream>
#include <string>
#include <vector>
#include <complex>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;

int dx[] = {-1, 0, 1, 0, -1, 0, 1, 0};
int dy[] = {0, -1, 0, -1, 0, 1, 0, 1};

int nx[] = {0, 1, 0, 1};
int ny[] = {0, 0, 1, 1};

typedef complex<double> point;
struct line : public vector<point> {
	line() {}
	line(const point& a, const point& b) { push_back(a); push_back(b); }
};

const double eps = 1e-10;
double dot  (const point& a, const point& b) { return (a*conj(b)).real(); }
double cross(const point& a, const point& b) { return (conj(a)*b).imag(); }

int ccw(const point& a, const point& b, const point& c) {
	point u=b-a, v=c-a;
	if(cross(u,v) > 0 ) return +1;
	if(cross(u,v) < 0 ) return -1;
	if(dot  (u,v) < 0 ) return +2;
	if(norm(u)<norm(v)) return -2;
	return 0;
}

int ccw(const line& s, const point& p) {
	return ccw(s[0], s[1], p);
}

bool contain(const line& s, const line& t) {
	return abs(s[0]-t[0]) < eps || abs(s[0]-t[1]) < eps ||
		   abs(s[1]-t[0]) < eps || abs(s[1]-t[1]) < eps;
}

bool intersectSS(const line& s, const line& t) {
	return ccw(s,t[0])*ccw(s,t[1]) <= 0
	    && ccw(t,s[0])*ccw(t,s[1]) <= 0;
}

typedef vector<vector<int> > Graph;

bool bipartite_matching_dfs(
	int v, const Graph &conn,
	vector<bool> &used, vector<int> &match)
{
	used[v] = true;
	for(int i = 0; i < conn[v].size(); ++i){
		int u = conn[v][i], w = match[u];
		if(w < 0 || !used[w] && bipartite_matching_dfs(w, conn, used, match)){
			match[v] = u;
			match[u] = v;
			return true;
		}
	}
	return false;
}
int bipartite_matching(const Graph &conn){
	int res = 0;
	vector<int> match(conn.size(), -1);
	vector<bool> used(conn.size(), false);
	for(int v = 0; v < conn.size(); ++v){
		if(match[v] < 0){
			fill(used.begin(), used.end(), false);
			if(bipartite_matching_dfs(v, conn, used, match)){ ++res; }
		}
	}
	return res;
}

void add_edge(int s, int d, Graph& g)
{
	g[s].push_back(d);
}


int main(){
	int H, W;
	while(cin >> H >> W, (H||W)){
		vector<string> choco(H);
		for(int i = 0; i < H; ++i){ cin >> choco[i]; }

		int N = 0;
		vector<vector<int> > vert(W+1), hori(H+1);
		for(int i=0; i<H; i++)
		for(int j=0; j<W; j++) {
			if(choco[i][j] != '.') continue;
			for(int k=0; k<4; k++) {
				bool ok = true;
				for(int l=0; l<2; l++) {
					int nx = j + dx[2*k + l];
					int ny = i + dy[2*k + l];
					if(nx < 0 || ny < 0 || nx >= W || ny >= H) {
						ok = false;
						break;
					}

					if(choco[ny][nx] != '#') {
						ok = false;
						break;
					}
				}

				if(ok) {
					hori[i + ny[k]].push_back(j + nx[k]);
					vert[j + nx[k]].push_back(i + ny[k]);
					N++;
				}
			}
		}

		for(int i=0; i<H+1; i++) {
			sort(hori[i].begin(), hori[i].end());
		}

		for(int i=0; i<W+1; i++)
			sort(vert[i].begin(), vert[i].end());

		vector<line> l, r;
		for(int i=0; i<H+1; i++) {
			int S = hori[i].size();
			for(int j=0; j<S-1; j++) {
				bool c[2] = {0};
				for(int k=hori[i][j]; k<hori[i][j+1]; k++) {
					if(choco[i-1][k] != '#') c[0] = true;
					if(choco[i][k] != '#') c[1] = true;
				}

				if(!c[0] && !c[1]) {
					l.push_back(line(point(hori[i][j], i), point(hori[i][j+1], i)));
				}
			}
		}

		for(int i=0; i<W+1; i++) {
			int S = vert[i].size();
			for(int j=0; j<S-1; j++) {
				bool c[2] = {0};
				for(int k=vert[i][j]; k<vert[i][j+1]; k++) {
					if(choco[k][i-1] != '#') c[0] = true;
					if(choco[k][i] != '#') c[1] = true;
				}

				if(!c[0] && !c[1]) {
					r.push_back(line(point(i, vert[i][j]), point(i, vert[i][j+1])));
				}
				
			}
		}

		int M = l.size() + r.size();

		Graph graph(M);

		for(int i=0; i<l.size(); i++)
		for(int j=0; j<r.size(); j++) {
			if(intersectSS(l[i], r[j])) {
				int u = i, v = j+l.size();
				add_edge(u, v, graph);
			}
		}

		cout << N - (M - bipartite_matching(graph)) + 1 << endl;

	}
}

Measured memory_bytes: 1428