#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); }
};

namespace std {
	bool operator<(const point
& a, const point& b) {
		return a.real()!=b.real() ? a.real()<b.real() : a.imag()<b.imag();
	}
}

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(); }
point  unit (const point& v)                 { return v/abs(v);  }
point  vec  (const line& l)                  { return l[1]-l[0]; }

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;

char flow[5500][5500];

bool dfs(int p, int T, Graph& graph, vector<int>& level, vector<bool>& finished)
{
	if(p==T) return true;
	if(finished[p]) return false;
	
	finished[p]=true;
	
	for(int i=0; i<graph[p].size(); i++)
	{
		int next=graph[p][i];
		if(level[p] >= level[next]) continue;
		if(flow[p][next]) continue;
	
		if(dfs(next, T, graph, level, finished))
		{
			finished[p]=false;
			flow[p][next]+=1;
			flow[next][p]-=1;
			return true;
		}
	}
	
	return false;
}

int dinic(int S, int T, Graph& graph)
{
	bool end=false;
	int total=0;
	while(!end)
	{
		end=true;
		vector<int> level(graph.size(), -1);
		level[S]=0;
		
		queue<int> q;
		q.push(S);
		while(!q.empty())
		{
			int n=q.front(); q.pop();
			for(int i=0; i<graph[n].size(); i++)
			{
				int next=graph[n][i];
				if(level[next]!=-1) continue;
				if(flow[n][next]) continue;
				level[next]=level[n]+1;
				q.push(next);
			}
		}
		
		if(level[T]==-1) break;
		
		vector<bool> finished(graph.size());
		while(dfs(S, T, graph, level, finished))
		{
			total++;
			end=false;
		}
	}
	
	return total;
}



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

	flow[s][d]=0;
	flow[d][s]=1;
}


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])));
				}
				
			}
		}


		memset(flow, 0, sizeof(flow));

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

		Graph graph(M + 2);
		for(int i=0; i<l.size(); i++)
			add_edge(M, i, graph);

		for(int i=0; i<r.size(); i++)
			add_edge(i+l.size(), M+1, graph);

		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-dinic(M, M+1, graph)) + 1 << endl;


	}
	return 0;
}

Measured memory_bytes: 30000