#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

constexpr int INF = 1e9;
using weight = int;

struct edge {
    int to;
    weight cap;
    int rev;
};

using edges = std::vector<edge>;
using graph = std::vector<edges>;

void add_edge(graph& g, int from, int to, weight 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)});
}

void bfs(graph& g, std::vector<int>& level, int s) {
    for(int i=0; i<level.size(); ++i) {
        level[i] = -1;
    }
    level[s] = 0;
    std::queue<weight> que;
    que.push(s);
    while(!que.empty()) {
        int v = que.front(); que.pop();
        for(int i=0; i<g[v].size(); ++i) {
            edge& e = g[v][i];
            if(e.cap > 0 && level[e.to] < 0) {
                level[e.to] = level[v] + 1;
                que.push(e.to);
            }
        }
    }
}

weight dfs(graph& g, std::vector<int>& level, std::vector<int>& iter, int v, int t, weight 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(g, level, iter, e.to, t, std::min(f, e.cap));
            if(d > 0) {
                e.cap -= d;
                g[e.to][e.rev].cap += d;
                return d;
            }
        }
    }
    return 0;
}

// verified
weight max_flow(graph& g, int s, int t) {
    weight flow = 0;
    std::vector<int> level(g.size(), -1);
    std::vector<int> iter(g.size(), 0);
    int INF = 1e9;
    while(true) {
        bfs(g, level, s);
        if(level[t] < 0) {
            return flow;
        }
        for(int i=0; i<iter.size(); ++i) {
            iter[i] = 0;
        }
        weight f;
        while((f = dfs(g, level, iter, s, t, INF)) > 0) {
            flow += f;
        }
    }
}

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

    graph g(2 * H * W + 2);
    const int source = 2 * H * W;
    const int sink = 2 * H * W + 1;
    bool check = false;
    for(int i = 0; i < H; ++i) {
        for(int j = 0; j < W; ++j) {
            add_edge(g, i * W + j, i * W + j + H * W, (S[i][j] == 'X' ? INF : 1));
            if(i != 0) {
                add_edge(g, i * W + j + H * W, (i - 1) * W + j, 1);
            }
            if(i != H - 1) {
                add_edge(g, i * W + j + H * W, (i + 1) * W + j, 1);
            }
            if(j != 0) {
                add_edge(g, i * W + j + H * W, i * W + j - 1, 1);
            }
            if(j != W - 1) {
                add_edge(g, i * W + j + H * W, i * W + j + 1, 1);
            }

            if(S[i][j] == 'X') {
                add_edge(g, source, i * W + j, INF);
                check |= i == 0 || i == H - 1 || j == 0 || j == W - 1;
            }
        }
    }
    if(check) {
        cout << -1 << endl;
        return 0;
    }

    for(int i = 0; i < H; ++i) {
        add_edge(g, i * W, sink, 1);
        add_edge(g, i * W + W - 1, sink, 1);
    }
    for(int i = 0; i < W; ++i) {
        add_edge(g, i, sink, 1);
        add_edge(g, (H - 1) * W + i, sink, 1);
    }

    cout << max_flow(g, source, sink) << endl;
}


Measured memory_bytes: 3072