#include <iostream>
#include <iomanip>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define INF 1<<30

class MaxFlow {
    // 辺を表す構造体（行き先、容量、逆辺）
    struct edge {
        int to, cap, rev;
    };
    vector<vector<edge>> G;  // グラフの隣接リスト表現
    vector<int> level;       // sからの距離
    vector<int> iter;        // どこまで調べ終わったか

    // sからの最短距離をBFSで計算する
    void bfs(int s) {
        fill(level.begin(), level.end(), -1);
        queue<int> que;
        level[s] = 0;
        que.push(s);
        while (!que.empty()) {
            int v = que.front();
            que.pop();
            for(auto &e : G[v]){
                if (e.cap > 0 && level[e.to] < 0) {
                    level[e.to] = level[v] + 1;
                    que.push(e.to);
                }
            }
        }
    }

    // 増加パスをDFSで探す
    int dfs(int v, int t, int f) {
        if (v == t) return f;
        for (int &i = iter[v]; i < G[v].size(); i++) {
            edge &e = G[v][i];
            if (e.cap > 0 && level[v] < level[e.to]) {
                int d = dfs(e.to, t, min(f, e.cap));
                if (d > 0) {
                    e.cap -= d;
                    G[e.to][e.rev].cap += d;
                    return d;
                }
            }
        }
        return 0;
    }

public:
    MaxFlow(int V) : G(V), level(V), iter(V) {}

    // from から to へ向かう容量 cap の辺をグラフに追加する
    void add_edge(int from, int to, int cap) {
        G[from].push_back((edge){to, cap, static_cast<int>(G[to].size())});
        G[to].push_back((edge){from, 0, static_cast<int>(G[from].size()) - 1});
    }
    // s から t への最大流を計算する
    int max_flow(int s, int t) {
        int flow = 0;
        while (bfs(s), level[t] >= 0) {
            fill(iter.begin(), iter.end(), 0);
            int f;
            while ((f = dfs(s, t, INF)) > 0) flow += f;
        }
        return flow;
    }
};

int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

int main(){
    int H, W;
    cin >> H >> W;
    vector<string> S(H);
    for(int i=0; i<H; i++) cin >> S[i];

    for(int i=0; i<H; i++)
        if(S[i][0] == 'X' || S[i][W-1] == 'X'){
            cout << -1 << endl;
            return 0;
        }
    for(int i=0; i<W; i++)
        if(S[0][i] == 'X' || S[H-1][i] == 'X'){
            cout << -1 << endl;
            return 0;
        }

    MaxFlow mf(2*H*W+2);
    for(int i=0; i<H; i++)
        for(int j=0; j<W; j++)
            mf.add_edge(H*W+W*i+j, W*i+j, 1);

    for(int i=0; i<H; i++)
        for(int j=0; j<W; j++)
            for(int k=0; k<4; k++){
                int y = i + dy[k];
                int x = j + dx[k];
                if(y < 0 || y >= H || x < 0 || x >= W) continue;
                mf.add_edge(W*i+j, H*W+W*y+x, 1);
            }

    for(int i=0; i<H; i++){
        mf.add_edge(W*i+0, 2*H*W+1, 1);
        mf.add_edge(W*i+W-1, 2*H*W+1, 1);
    }
    for(int i=0; i<W; i++){
        mf.add_edge(W*0+i, 2*H*W+1, 1);
        mf.add_edge(W*(H-1)+i, 2*H*W+1, 1);
    }

    for(int i=0; i<H; i++)
        for(int j=0; j<W; j++)
            if(S[i][j] == 'X')
                mf.add_edge(2*H*W, W*i+j, 1<<29);
    cout << mf.max_flow(2*H*W, 2*H*W+1) << endl;
    return 0;
}

Measured memory_bytes: 2944