#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rrep(i, n) for (int i = (int)(n - 1); i >= 0; i--)
#define all(x) (x).begin(), (x).end()
#define sz(x) int(x.size())
using namespace std;
using ll = long long;
const int INF = 1e9;
const ll LINF = 1e18;
template <class T>
void get_unique(vector<T>& x) {
    x.erase(unique(x.begin(), x.end()), x.end());
}
template <class T>
bool chmax(T& a, const T& b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T>
bool chmin(T& a, const T& b) {
    if (b < a) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T>
vector<T> make_vec(size_t a) {
    return vector<T>(a);
}
template <class T, class... Ts>
auto make_vec(size_t a, Ts... ts) {
    return vector<decltype(make_vec<T>(ts...))>(a, make_vec<T>(ts...));
}
template <typename T>
istream& operator>>(istream& is, vector<T>& v) {
    for (int i = 0; i < int(v.size()); i++) {
        is >> v[i];
    }
    return is;
}
template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < int(v.size()); i++) {
        os << v[i];
        if (i < sz(v) - 1) os << ' ';
    }
    return os;
}
struct UnionFind {
    vector<int> data;
    UnionFind(int size) : data(size, -1) {
    }
    int root(int x) {
        return (data[x] < 0) ? x : data[x] = root(data[x]);
    }
    bool unite(int x, int y) {
        x = root(x);
        y = root(y);
        if (x != y) {
            if (data[y] < data[x]) swap(x, y);
            data[x] += data[y];
            data[y] = x;
        }
        return x != y;
    }
    bool find(int x, int y) {
        return root(x) == root(y);
    }
    int size(int x) {
        return -data[root(x)];
    }
};
int main() {
    int h, w;
    cin >> h >> w;
    vector<string> s(h);
    cin >> s;
    s[0][0] = s[0][w - 1] = s[h - 1][0] = s[h - 1][w - 1] = '#';
    vector<vector<int>> ys(w), xs(h);
    rep(i, h) rep(j, w) {
        if (s[i][j] == '#') {
            ys[j].push_back(i);
            xs[i].push_back(j);
        }
    }
    int ans = INF;

    UnionFind uf(h + w);
    rep(y, h) rep(i, sz(xs[y]) - 1) {
        uf.unite(xs[y][i], xs[y][i + 1]);
    }
    rep(x, w) rep(i, sz(ys[x]) - 1) {
        uf.unite(ys[x][i] + w, ys[x][i + 1] + w);
    }

    int sz_y = 0, sz_x = 0;
    rep(i, w) sz_x += uf.root(i) == i;
    rep(i, h) sz_y += uf.root(i + w) == i + w;
    cout << min(sz_y - 1, sz_x - 1) << '\n';
}
#include<bits/stdc++.h>
#pragma GCC optimize("O3,unroll-loops,fast-math")
#include <ext/pb_ds/tree_policy.hpp> // #include<ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp> //#include<ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds; //using namespace __gnu_pbds;
#define pb push_back
#define ins insert
#define var auto
#define F first
#define S second
#define mp make_pair
using namespace std;
typedef long long ll;
//#define int ll
typedef pair<int,int> pii;
template <class T> using oset = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>;
const int Max = 1000 + 10;
const int LOG = 20;
const int Mod = 1e9 + 7;
const int SQ = 100000;
const ll INF = 1e18;
const int BMSK = 4e6;

ll pw(ll a , int b = Mod - 2)
{
	if(b == 0) return 1;
	ll half = pw(a , b / 2);
	if(b % 2) return half * half % Mod * a % Mod;
	return half * half % Mod;
}

char S[Max][Max];
vector<pair<int , int> > N[Max][Max];
int val[Max][Max];
bool seen[Max][Max];
int DFS(int I , int J)
{
	seen[I][J] = true;
	int sum = val[I][J];
	for(pair<int , int> u : N[I][J])
	{
		int i = u.F , j = u.S;
		if(!seen[i][j]) sum += DFS(i , j);
	}
	return sum;
}
void solve()
{
	int h , w; cin >> h >> w;
	for(int i = 1 ; i <= h ; i++)
	{
		for(int j = 1 ; j <= w ; j++)
		{
			cin >> S[i][j];
			if(i == 1 || i == h) if(j == 1 || j == w) S[i][j] = '#' , val[i][j] = 1;
			if(S[i][j] == '#')
			{
				N[i][j].pb(mp(0 , j));
				N[i][j].pb(mp(i , 0));
				N[0][j].pb(mp(i , j));
				N[i][0].pb(mp(i , j));
			}
		}
	}

	int ans1 = 0;
	for(int i = 1 ; i <= h ; i++)
	{
		if(!seen[i][0])
		{
			ans1 += DFS(i , 0) == 0;
		}
	}
	for(int i = 0 ; i <= h ; i++)
		for(int j = 0 ; j <= w ; j++)
			seen[i][j] = 0;
	int ans2 = 0;
	for(int j = 1 ; j <= w ; j++)
	{
		if(!seen[0][j])
		{
			ans2 += DFS(0 , j) == 0;
		}
	}
	cout << min(ans1 , ans2) << '\n';
}

int32_t main()
{
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cout << '\n';
	//int t;cin >> t;
	//while(t--)
	solve();
}
