#include <algorithm>
#include <array>
#include <cstdio>
#include <iostream>
#include <queue>
#include <string>
#include <vector>

using namespace std;
#define int long long
#define ll long long
#define INF 1LL << 33
#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define SHOW(p) \
    if (test)   \
        cout << #p " : " << p << endl;
//bool test = true;
bool test = false;
int H, W;
vector<string> s;
vector<pair<int, int>> gs, gs2;
vector<bool> col, row, col2, row2;
bool update()
{
    bool update_onece = false;
    bool update = true;
    while (update) {
        update = false;
        for (auto it = gs.begin(); it != gs.end();) {
            if (row.at(it->first)) {
                if (!col.at(it->second)) {
                    update = col.at(it->second) = true;
                    it = gs.erase(it);
                } else {
                    it++;
                }
            } else if (col.at(it->second)) {
                if (!row.at(it->first)) {
                    update = row.at(it->first) = true;
                    it = gs.erase(it);
                } else {
                    it++;
                }
            } else {
                it++;
            }
            if (test) {
                cout << it->first << ":" << it->second << endl;
            }
        }
        if (update) {
            update_onece = true;
        }
    }
    return update_onece;
}
bool update2()
{
    bool update_onece = false;
    bool update = true;
    while (update) {
        update = false;
        for (auto it = gs2.begin(); it != gs2.end();) {
            if (row2.at(it->first)) {
                if (!col2.at(it->second)) {
                    update = col2.at(it->second) = true;
                    it = gs2.erase(it);
                } else {
                    it++;
                }
            } else if (col2.at(it->second)) {
                if (!row2.at(it->first)) {
                    update = row2.at(it->first) = true;
                    it = gs2.erase(it);
                } else {
                    it++;
                }
            } else {
                it++;
            }
            if (test) {
                cout << it->first << ":" << it->second << endl;
            }
        }
        if (update) {
            update_onece = true;
        }
    }
    return update_onece;
}
signed main()
{
    cin >> H >> W;
    s.resize(H);
    col.resize(W, false);
    row.resize(H, false);
    row.at(0) = row.at(H - 1) = col.at(0) = col.at(W - 1) = true;
    REP(i, H)
    {
        cin >> s.at(i);
        REP(j, W)
        {
            if (s.at(i).at(j) == '#') {
                gs.push_back({i, j});
            }
        }
    }
    update();
    row2 = row;
    col2 = col;
    gs2 = gs;
    //cols
    int ans_c = 0;
    for (int x = 0; x < H; x++) {
        if (row.at(x)) {
            continue;
        }
        ans_c++;
        row.at(x) = true;
        update();
    }
    //cols
    int ans_r = 0;
    for (int x = 0; x < W; x++) {
        if (col2.at(x)) {
            continue;
        }
        ans_r++;
        col2.at(x) = true;
        update2();
    }
    if (ans_r > ans_c) {
        cout << ans_c << endl;
    } else {
        cout << ans_r << endl;
    }
    return 0;
}

#include <bits/stdc++.h>
#define maxn 2086

using namespace std;

int n, m;
char s[maxn][maxn];

int fa[maxn], siz[maxn];

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

set<int> st[2];


int main(){
	scanf("%d%d", &n, &m);
	for(int i = 1;i <= n;i++) scanf("%s", s[i] + 1);
	for(int i = 1;i <= n + m;i++) fa[i] = i, siz[i] = 1;
	s[1][1] = s[n][1] = s[1][m] = s[n][m] = '#';
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= m;j++){
			if(s[i][j] == '#'){
				int x = find(i), y = find(j + n);
				if(x == y) continue;
				if(siz[x] > siz[y]) swap(x, y);
				fa[x] = y, siz[y] += siz[x];
			}
		}
	}
	for(int i = 1;i <= n;i++) st[0].insert(find(i));
	for(int i = 1;i <= m;i++) st[1].insert(find(i + n));
	printf("%d", min(st[0].size(), st[1].size()) - 1);
}