#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using PII = pair<int, int>;
using VI = vector<int>;
struct Dinic {
  const int static INF = 1 << 30;
  struct Edge {
    int from, to;
    int cap;
    int flow = 0;
    Edge(int from, int to, int cap) : from(from), to(to), cap(cap) {}
  };
  int n, m = 0, src, dest;
  int LIM = 1;
  vector<Edge> edges;
  vector<VI> adj;
  VI level, ptr;
  Dinic(int n) : n(n), adj(n), level(n), ptr(n) {}
  void add_edge(int u, int v, int cap) {
    edges.emplace_back(u, v, cap);
    adj[u].push_back(m);
    m++;
    edges.emplace_back(v, u, 0);
    adj[v].push_back(m);
    m++;
  }
  bool bfs() {
    fill((level).begin(), (level).end(), -1);
    level[src] = 0;
    VI q(n + 10);
    int qh = 0, qt = -1;
    q[++qt] = src;
    while (qh <= qt) {
      int u = q[qh++];
      for (int id : adj[u]) {
        int v = edges[id].to;
        if (edges[id].cap - edges[id].flow < LIM) continue;
        if (level[v] != -1) continue;
        level[v] = level[u] + 1;
        q[++qt] = v;
      }
    }
    return level[dest] != -1;
  }
  int dfs(int u, int pushed) {
    if (pushed == 0) return 0;
    if (u == dest) return pushed;
    for (int &cid = ptr[u]; cid < ((int)(adj[u]).size()); cid++) {
      int id = adj[u][cid];
      int v = edges[id].to;
      if (level[u] + 1 != level[v]) continue;
      int tr = dfs(v, min(pushed, edges[id].cap - edges[id].flow));
      if (tr > 0) {
        edges[id].flow += tr;
        edges[id ^ 1].flow -= tr;
        return tr;
      }
    }
    return 0;
  }
  int max_flow(int s, int t) {
    src = s, dest = t;
    int f = 0;
    while (bfs()) {
      fill((ptr).begin(), (ptr).end(), 0);
      while (int pushed = dfs(s, INF)) f += pushed;
    }
    return f;
  }
};
struct Bipartite {
  int L, R;
  Dinic net;
  Bipartite(int l, int r) : L(l), R(r), net(l + r + 2) {}
  void add_edge(int u, int v) { net.add_edge(1 + u, 1 + L + v, 1); }
  int max_matching() {
    int s = 0, t = 1 + L + R;
    for (int u = (0); u < (L); u++) net.add_edge(s, 1 + u, 1);
    for (int v = (0); v < (R); v++) net.add_edge(1 + L + v, t, 1);
    return net.max_flow(s, t);
  }
};
const int N = 205;
string grid[N];
VI horz[N][N], vert[N][N];
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  int n, m;
  cin >> n >> m;
  int tot = 0;
  for (int i = 0; i < n; i++) {
    cin >> grid[i];
    for (char c : grid[i]) {
      if (c == '#') tot++;
    }
  }
  int lt = 0, rt = 0;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (grid[i][j] != '#') continue;
      if (i + 1 < n && grid[i + 1][j] == '#') {
        vert[i][j].push_back(lt);
        vert[i + 1][j].push_back(lt);
        ++lt;
      }
      if (j + 1 < m && grid[i][j + 1] == '#') {
        horz[i][j].push_back(rt);
        horz[i][j + 1].push_back(rt);
        ++rt;
      }
    }
  }
  Bipartite bp(lt, rt);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      for (int u : vert[i][j]) {
        for (int v : horz[i][j]) {
          bp.add_edge(u, v);
        }
      }
    }
  }
  int mm = bp.max_matching();
  int br = lt + rt - mm;
  int ans = tot - br;
  cout << ans << endl;
  return 0;
}
