#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast,no-stack-protector")
using namespace std;
function<void(void)> ____ = []() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
};
template <typename T>
vector<T> &operator<<(vector<T> &__container, T x) {
  __container.push_back(x);
  return __container;
}
template <typename T>
ostream &operator<<(ostream &out, vector<T> &__container) {
  for (T _ : __container) out << _ << ' ';
  return out;
}
const int MAXN = 1e5 + 7;
struct EDGE {
  int to, cap, rev;
  EDGE(){};
  EDGE(int to, int cap, int rev) : to(to), cap(cap), rev(rev){};
};
vector<EDGE> G[MAXN];
int iter[MAXN], rk[MAXN];
void ADDEDGE(int u, int v, int cap) {
  G[u].push_back(EDGE(v, cap, (int)G[v].size()));
  G[v].push_back(EDGE(u, 0, (int)G[u].size() - 1));
}
bool bfs() {
  memset(rk, 0, sizeof(rk));
  memset(iter, 0, sizeof(iter));
  rk[0] = 1;
  queue<int> que;
  que.push(0);
  while (!que.empty()) {
    int u = que.front();
    que.pop();
    for (auto e : G[u]) {
      if (!e.cap or rk[e.to]) continue;
      rk[e.to] = rk[u] + 1;
      que.push(e.to);
    }
  }
  return rk[MAXN - 1] != 0;
}
int dfs(int u, int flow) {
  if (u == MAXN - 1) return flow;
  for (int &i = iter[u]; i < (int)G[u].size(); i++) {
    auto &e = G[u][i];
    if (!e.cap or rk[e.to] != rk[u] + 1) continue;
    int d = dfs(e.to, min(e.cap, flow));
    if (d) {
      e.cap -= d;
      G[e.to][e.rev].cap += d;
      return d;
    }
  }
  return 0;
}
int Dinic() {
  int flow = 0;
  while (bfs()) {
    int d = dfs(0, 0x3f3f3f3f);
    while (d) {
      flow += d;
      d = dfs(0, 0x3f3f3f3f);
    }
  }
  return flow;
}
int n, m, idud[222][222], idlr[MAXN][222];
char g[222][222];
void solve() {
  scanf("%d", &n);
  scanf("%d", &m);
  int cur = 1, cnt = 0, tot = 0;
  for (int i = 1; i <= n; i++) scanf("%s", g[i] + 1);
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
      if (g[i][j] == '#') tot++;
  for (int i = 1; i < n; i++)
    for (int j = 1; j <= m; j++) idud[i][j] = cur++;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j < m; j++) idlr[i][j] = cur++;
  for (int i = 1; i < n; i++)
    for (int j = 1; j <= m; j++)
      if (g[i][j] == '#' and g[i + 1][j] == '#')
        ADDEDGE(0, idud[i][j], 1), cnt++;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j < m; j++)
      if (g[i][j] == '#' and g[i][j + 1] == '#')
        ADDEDGE(idlr[i][j], MAXN - 1, 1), cnt++;
  for (int i = 1; i < n; i++)
    for (int j = 1; j <= m; j++) {
      if (g[i][j] == '#' and g[i + 1][j] == '#') {
        if (g[i][j - 1] == '#') ADDEDGE(idud[i][j], idlr[i][j - 1], 0x3f3f3f3f);
        if (g[i + 1][j - 1] == '#')
          ADDEDGE(idud[i][j], idlr[i + 1][j - 1], 0x3f3f3f3f);
        if (g[i][j + 1] == '#') ADDEDGE(idud[i][j], idlr[i][j], 0x3f3f3f3f);
        if (g[i + 1][j + 1] == '#')
          ADDEDGE(idud[i][j], idlr[i + 1][j], 0x3f3f3f3f);
      }
    }
  cout << tot - (cnt - Dinic()) << "\n";
}
int main() {
  solve();
  return 0;
}
