#include <bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define full(a) memset(a, 0x3f, sizeof(a))
#define mset(a, b) memset(a, b, sizeof(a))
#define cpy(a,b) memcpy(a, b, sizeof(a))
#define fornext(x, i) for(signed i = hd[x], y = ver[i]; i; i = nxt[i], y = ver[i])
#define Rep(i, a, b) for(signed i = (signed)(a); i <= (signed)(b); ++i)
#define dRep(i, a, b) for(signed i = (signed)(a); i >= (signed)(b); --i)
#define IOset(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout);
#define pb push_back
#define It iterator
#define endl '\n'
#define un unsigned
#define int ll
#define ll long long
#define db double
#define rept cerr<<1.0*clock()/CLOCKS_PER_SEC<<endl;
#define dbg cout<<"c "
#define dbug(x) cerr << #x " = " << (x) << endl
template<typename _T> inline void _prt(_T _d) { cerr << _d << ' '; }
template <typename _T, typename ...Args> inline void _prt(_T _d, Args ..._a) { _prt(_d), _prt(_a...); }
template <typename _T, typename ...Args> inline void prt(_T _d, Args ..._a) { _prt(_d), _prt(_a...), cerr<<endl; }
template <typename _T, typename ...Args> inline void prt(_T _d) { cerr << _d <<endl; }
template<typename _T> inline void rd(_T &_d) {
	signed _f; char _c; _f = 1,_d = 0; while (_c = getchar(), !isdigit(_c)) if(_c=='-') _f=-1;
	while (isdigit(_c)) _d = _d * 10 + _c - '0', _c = getchar();
	_d=_f*_d;
}
template <typename _T, typename ...Args> inline void rd(_T &_d, Args &..._a) { rd(_d); rd(_a...); }

const int N=2005;
int fa[N],ex[N][2],n,m,vis[N];
char s[N];

int find(int x) {
	if (fa[x] == x) return x;
	return fa[x] = find(fa[x]);
}

void uni(int x,int y) {
	int p=find(x),q=find(y);
	if(p==q) return;
	fa[p]=q,ex[q][0]|=ex[p][0],ex[q][1]|=ex[p][1];
}

signed main() {
	rd(n,m);
	Rep(i,1,n+m) fa[i]=i;
	Rep(i,1,n) ex[i][0]=1;
	Rep(i,n+1,n+m) ex[i][1]=1;
	Rep(i,1,n) {
		scanf("%s",s+1);
		Rep(j,1,m) if(s[j]=='#') uni(i,j+n);
	}
	uni(1,n+1),uni(n,n+1),uni(1,n+m),uni(n,n+m);
	int rec=0,ans=0;
	Rep(i,1,n+m) find(i);
	Rep(i,1,n+m) if(!vis[fa[i]]&&fa[i]!=fa[1]&&ex[fa[i]][0]) ++ans,vis[fa[i]]=1;
	clr(vis);
	Rep(i,1,n+m) if(!vis[fa[i]]&&fa[i]!=fa[1]&&ex[fa[i]][1]) ++rec,vis[fa[i]]=1;
	cout<<min(ans,rec)<<endl;
	return 0;
}
#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define INF 1000000000
#define LINF 1000000000000000000
#define MOD 1000000007
#define mod 998244353
#define INF63 1061109567
#define INF127 9187201950435737471
#define UINF 18446744073709551615
#define F first
#define S second
#define ll long long
#define N 1010
using namespace std;
char buf[N];
string s[N];
ll n,m,ans=0;
bool vis[N*N];
bool mark_r[N],mark_c[N];
vector<ll> vt[N*N];
void dfs(ll x)
{
	vis[x]=true;
	ll i;
	for(i=0;i<vt[x].size();i++)
	{
		if(!vis[vt[x][i]])
		{
			dfs(vt[x][i]);
		}
	}
	return;
}
int main(){
	ll i,j,k,m1,m2;
	scanf("%lld%lld",&n,&m);
	for(i=0;i<n;i++)
	{
		scanf("%s",&buf);
		s[i]=buf;
	}
	for(i=0;i<n;i++)
	{
		for(j=0;j<m;j++)
		{
			if(s[i][j]=='#')
			{
				mark_r[i]=true;
				mark_c[j]=true;
				for(k=j+1;k<m;k++)
				{
					if(s[i][k]=='#')
					{
						vt[i*m+j].push_back(i*m+k);
						vt[i*m+k].push_back(i*m+j);
						break;
					}
				}
				for(k=i+1;k<n;k++)
				{
					if(s[k][j]=='#')
					{
						vt[i*m+j].push_back(k*m+j);
						vt[k*m+j].push_back(i*m+j);
						break;
					}
				}
			}
		}
	}
	for(i=0;i<n;i++)
	{
		if(s[i][0]=='#'&&(!vis[i*m]))
		{
			dfs(i*m);
		}
		if(s[i][m-1]=='#'&&(!vis[i*m+m-1]))
		{
			dfs(i*m+m-1);
		}
	}
	for(i=0;i<m;i++)
	{
		if(s[0][i]=='#'&&(!vis[i]))
		{
			dfs(i);
		}
		if(s[n-1][i]=='#'&&(!vis[(n-1)*m+i]))
		{
			dfs((n-1)*m+i);
		}
	}
	for(i=1;i+1<n;i++)
	{
		for(j=1;j+1<m;j++)
		{
			if(s[i][j]=='#'&&(!vis[i*m+j]))
			{
				ans++;
				dfs(i*m+j);
			}
		}
	}
	m1=m2=0;
	for(i=1;i+1<n;i++)
	{
		if(!mark_r[i])
		{
			m1++;
		}
	}
	for(i=1;i+1<m;i++)
	{
		if(!mark_c[i])
		{
			m2++;
		}
	}
	ans+=min(m1,m2);
	printf("%lld\n",ans);
	return 0;
}