#include <bits/stdc++.h>
#pragma GCC optimize("Ofast", "unroll-loops", "omit-frame-pointer", "inline")
#pragma GCC option("arch=native", "tune=native", "no-zero-upper")
#pragma GCC target("avx2")
using namespace std;
const int mod = 1e9 + 7;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int mul(int a, int b) { return ((a)*1ll * (b)) % mod; }
void add(int& a, int b) {
  a += b;
  if (a >= mod) a -= mod;
}
int sub(int a, int b) {
  a -= b;
  if (a < 0) {
    a += mod;
  }
  return a;
}
int powz(int a, int b) {
  int res = 1;
  while (b) {
    if (b & 1) {
      res = mul(res, a);
    }
    b /= 2;
    a = mul(a, a);
  }
  return res;
}
template <typename A, typename B>
istream& operator>>(istream& input, pair<A, B>& x) {
  input >> x.first >> x.second;
  return input;
}
template <typename A>
istream& operator>>(istream& input, vector<A>& x) {
  for (auto& i : x) input >> i;
  return input;
}
template <typename A>
ostream& operator<<(ostream& output, vector<A>& x) {
  for (auto& i : x) output << i << ' ';
  return output;
}
template <typename T>
inline bool uax(T& x, T y) {
  return (y > x) ? x = y, true : false;
}
template <typename T>
inline bool uin(T& x, T y) {
  return (y < x) ? x = y, true : false;
}
template <typename T>
vector<pair<T, int>> getvec(int n) {
  vector<pair<T, int>> a(n);
  for (int i = 0; i < a.size(); i++) {
    cin >> a[i].first;
    a[i].second = i;
  }
  return a;
}
const int N = 200005;
struct DSU {
  vector<int> fa, sz;
  DSU(int n) {
    fa.clear();
    sz.clear();
    fa.resize(n);
    sz.resize(n);
    for (int i = 0; i < n; i++) {
      fa[i] = i;
      sz[i] = 1;
    }
  }
  int get(int x) {
    if (fa[x] == x) {
      return x;
    }
    return fa[x] = get(fa[x]);
  }
  void merge(int x, int y) {
    x = get(x);
    y = get(y);
    if (x == y) {
      return;
    }
    if (sz[x] < sz[y]) {
      swap(x, y);
    }
    fa[y] = x;
    sz[x] += sz[y];
    sz[y] = 0;
  }
};
void solve() {
  int n, m;
  cin >> n >> m;
  vector<string> a(n);
  cin >> a;
  DSU ds(n * m);
  vector<int> empty(m);
  vector<int> empty2(n);
  for (int i = 0; i < m; i++) {
    for (int j = 0; j < n; j++) {
      if (a[j][i] == '#') {
        empty[i] = 1;
      }
    }
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (a[i][j] == '#') {
        empty2[i] = 1;
      }
    }
  }
  for (int i = 0; i < n; i++) {
    int fst = 0;
    while (fst < m && a[i][fst] == '.') {
      fst++;
    }
    if (fst == m) {
      int flag = 0;
      for (int j = 0; j < m; j++) {
        if (empty[j] == 0) {
          flag = 1;
        }
      }
      if (flag == 0) {
        cout << -1;
        return;
      }
    }
    int lst = m - 1;
    while (lst >= 0 && a[i][lst] == '.') {
      lst--;
    }
    int flag = 0;
    for (int j = fst; j <= lst; j++) {
      if (a[i][j] == '.') {
        cout << -1;
        return;
      }
    }
    42;
    for (int j = fst; j <= lst; j++) {
      ds.merge(i * m + j, i * m + fst);
      if (i && a[i - 1][j] == '#') {
        ds.merge((i - 1) * m + j, i * m + fst);
      }
    }
  }
  for (int i = 0; i < m; i++) {
    int fst = 0;
    while (fst < n && a[fst][i] == '.') {
      fst++;
    }
    if (fst == n) {
      int flag = 0;
      for (int j = 0; j < n; j++) {
        if (empty2[j] == 0) {
          flag = 1;
        }
      }
      if (flag == 0) {
        cout << -1;
        return;
      }
    }
    int lst = n - 1;
    while (lst >= 0 && a[lst][i] == '.') {
      lst--;
    }
    for (int j = fst; j <= lst; j++) {
      if (a[j][i] == '.') {
        cout << -1;
        return;
      }
    }
  }
  int ans = 0;
  for (int i = 0; i < n * m; i++) {
    if (ds.get(i) == i && a[i / m][i % m] == '#') {
      ans++;
    }
  }
  cout << ans;
}
signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  int tc = 1;
  for (int _ = 0; _ < tc; _++) {
    solve();
    if (_ != tc - 1) {
      cout << '\n';
    }
  }
}
