#include <bits/stdc++.h>
#define forn(i,s,t) for(register int i=(s);i<=(t);++i)
using namespace std;
const int N = 1e3 + 3;
int H, W;
char mp[N][N];
int fa[N<<1];
inline void init() {forn(i,1,H + W) fa[i] = i;}
int Fnd(int u) {return fa[u] == u ? u : fa[u] = Fnd(fa[u]);}
void Mrg(int u, int v) {fa[Fnd(u)] = Fnd(v);}
set<int> s1, s2;
int main() {
	scanf("%d%d", &H, &W); init();
	forn(i,1,H) scanf("%s", mp[i] + 1);
	fa[H] = fa[H + 1] = fa[H + W] = fa[1];
	forn(i,1,H) forn(j,1,W) if(mp[i][j] == '#')
		Mrg(i, H + j);
	int res1 = 0, res2 = 0;
	forn(i,1,H) s1.insert(Fnd(i));
	forn(i,1,W) s2.insert(Fnd(i + H));
	printf("%d\n", min(s1.size(), s2.size()) - 1);
	return 0;
}
#include <bits/stdc++.h>
using namespace std;
using ll = int64_t;
using ld = long double;
using P = pair<ll, ll>;
using Vec = vector<ll>;
using VecP = vector<P>;
template <class T>
using Vec2 = vector<vector<T>>;
#define REP(i, m, n) for(ll i = (m); i < (n); ++i)
#define REPN(i, m, n) for(ll i = (m); i <= (n); ++i)
#define REPR(i, m, n) for(ll i = (m)-1; i >= (n); --i)
#define REPNR(i, m, n) for(ll i = (m); i >= (n); --i)
#define rep(i, n) REP(i, 0, n)
#define repn(i, n) REPN(i, 1, n)
#define repr(i, n) REPR(i, n, 0)
#define repnr(i, n) REPNR(i, n, 1)
#define all(s) (s).begin(), (s).end()
template <class T1, class T2>
bool chmax(T1 &a, const T2 b) { return a < b ? a = b, true : false; }
template <class T1, class T2>
bool chmin(T1 &a, const T2 b) { return a > b ? a = b, true : false; }
template <class T>
istream &operator>>(istream &is, vector<T> &v) { for (T &i : v) is >> i; return is; }
template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) { for (const T &i : v) os << i << ' '; return os; }
void _co() { cout << '\n'; }
template <class Head, class... Tail>
void _co(Head&& head, Tail&&... tail) { cout << ' ' << head; _co(forward<Tail>(tail)...); }
template <class Head, class... Tail>
void co(Head&& head, Tail&&... tail) { cout << head; _co(forward<Tail>(tail)...); }
void ce() { cerr << '\n'; }
template <class Head, class... Tail>
void ce(Head&& head, Tail&&... tail) { cerr << head << ' '; ce(forward<Tail>(tail)...); }
void sonic() { ios::sync_with_stdio(false); cin.tie(nullptr); }
void setp(const int n) { cout << fixed << setprecision(n); }
constexpr int64_t INF = 1000000000000000001;
constexpr int64_t MOD = 1000000007;
constexpr int64_t MOD_N = 998244353;
constexpr long double EPS = 1e-11;
const double PI = acos(-1);

struct union_find {
    vector<int64_t> par;
    vector<int64_t> sz;

    union_find(int64_t _n) : par(_n), sz(_n, 1) {
        for (int64_t i = 0; i < _n; ++i) par[i] = i;
    }

    int64_t root(int64_t x) {
        if (par[x] == x) return x;
        return par[x] = root(par[x]);
    }

    void unite(int64_t x, int64_t y) {
        x = root(x), y = root(y);
        if (x != y) {
            if (sz[x] < sz[y]) swap(x, y);
            par[y] = x;
            sz[x] += sz[y];
        }
    }

    int64_t size(int64_t x) { return sz[root(x)]; }

    bool is_same(int64_t x, int64_t y) { return root(x) == root(y); }
};

int main(void) {
    ll h, w;
    cin >> h >> w;
    vector<string> s(h);
    for (auto &i : s) cin >> i;
    union_find uf(h + w);

    uf.unite(0, h - 1);
    uf.unite(h, h + w - 1);
    uf.unite(0, h);
    rep(i, h) {
        rep(j, w) {
            if (s[i][j] == '#')
                uf.unite(i, h + j);
        }
    }

    union_find x = uf, y = uf;

    ll a = 0, b = 0;
    rep(i, h - 1) {
        if (!x.is_same(i, h - 1)) {
            ++a;
            x.unite(i, h - 1);
        }
    }
    REP(i, h, h + w - 1) {
        if (!y.is_same(i, h + w - 1)) {
            ++b;
            y.unite(i, h + w - 1);
        }
    }
    co(min(a, b));

    return 0;
}