#include<bits/stdc++.h>

#define debug(x) cerr << #x << ": " << x << '\n'
#define debugArray(x,n) for(long long hoge = 0; (hoge) < (n); ++ (hoge)) cerr << #x << "[" << hoge << "]: " << x[hoge] << '\n'
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef vector<ll> vll;
const ll INF = LLONG_MAX/2;
const ll MOD = 1e9+7;


struct Dinic {
    typedef long long flow_type;
    struct edge {
        int src, dst;
        flow_type capacity, flow;
        size_t rev;
    };
    int n;
    vector<vector<edge>> adj;
    Dinic(int n) : n(n), adj(n) { }
    void add_edge(int src, int dst, flow_type capacity) {
        adj[src].push_back({src, dst, capacity, 0, adj[dst].size()});
        adj[dst].push_back({dst, src, 0, 0, adj[src].size()-1});
    }
    flow_type max_flow(int s, int t) {
        vector<int> level(n), iter(n);
        function<int(void)> levelize = [&]() { // foward levelize
            level.assign(n, -1); level[s] = 0;
            queue<int> Q; Q.push(s);
            while (!Q.empty()) {
                int u = Q.front(); Q.pop();
                if (u == t) break;
                for (auto &e: adj[u]) {
                    if (e.capacity > e.flow && level[e.dst] < 0) {
                        Q.push(e.dst);
                        level[e.dst] = level[u] + 1;
                    }
                }
            }
            return level[t];
        };
        function<flow_type(int, flow_type)> augment = [&](int u, flow_type cur) {
            if (u == t) return cur;
            for (int &i = iter[u]; i < (ll)adj[u].size(); ++i) {
                edge &e = adj[u][i], &r = adj[e.dst][e.rev];
                if (e.capacity > e.flow && level[u] < level[e.dst]) {
                    flow_type f = augment(e.dst, min(cur, e.capacity - e.flow));
                    if (f > 0) {
                        e.flow += f;
                        r.flow -= f;
                        return f;
                    }
                }
            }
            return flow_type(0);
        };
        for (int u = 0; u < n; ++u) // initialize
            for (auto &e: adj[u]) e.flow = 0;

        flow_type flow = 0;
        while (levelize() >= 0) {
            fill(iter.begin(),iter.end(), 0);
            for (flow_type f; (f = augment(s, INF)) > 0; )
                flow += f;
        }
        return flow;
    }
    const vector<edge> operator[](const ll k){return adj[k];}
};
signed main(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  ll H,W;cin>>H>>W;
  Dinic g(2*H*W+2);
  ll src=2*H*W,dst=2*H*W+1;
  bool ok=true;
  for(ll i=0;i<H;i++){
    string S;cin>>S;
    for(ll j=0;j<W;j++){
      if(S[j]=='X'){
        g.add_edge(src,i*W+j,INF);
        g.add_edge(i*W+j,H*W+i*W+j,INF);
      }else{
        g.add_edge(i*W+j,H*W+i*W+j,1);
      }
      if(i>0)g.add_edge(H*W+(i-1)*W+j,i*W+j,INF);
      if(i+1<H)g.add_edge(H*W+(i+1)*W+j,i*W+j,INF);
      if(j>0)g.add_edge(H*W+i*W+j-1,i*W+j,INF);
      if(j+1<W)g.add_edge(H*W+i*W+j+1,i*W+j,INF);
    }
    if(S[0]=='X'||S.back()=='X'){
      ok=false;
    }
  }
  if(!ok){
    cout<<-1<<endl;
    return 0;
  }
  for(ll i=0;i<H;i++){
    g.add_edge(H*W+i*W,dst,INF);
    g.add_edge(H*W+i*W+W-1,dst,INF);
  }
  for(ll j=0;j<W;j++){
    g.add_edge(H*W+j,dst,INF);
    g.add_edge(H*W+(H-1)*W+j,dst,INF);
  }
  cout<<g.max_flow(src,dst)<<endl;
  return 0;
}


Measured memory_bytes: 6264