#include "bits/stdc++.h"

using namespace std;
using ll = long long;
using ld = long double;
using P = pair<int, int>;
constexpr ld EPS = 1e-12;
constexpr int INF = numeric_limits<int>::max() / 2;
constexpr int MOD = 1e9 + 7;

template <typename T>
void printv(const vector<T> &v)
{
    int sz = v.size();
    for (int i = 0; i < sz; i++)
    {
        cout << v[i] << " \n"[i == sz - 1];
    }
}

class Dinic
{
    using type = int;
    const int INF = 1e9;
    struct Edge
    {
        type to, cap, rev;
        Edge(int _t, int _c, int _r) : to(_t), cap(_c), rev(_r) {}
    };

    using Graph = std::vector<std::vector<Edge>>;
    int V;
    Graph G;
    std::vector<int> level;
    std::vector<int> iter;

    void bfs(int s)
    {
        fill(level.begin(), level.end(), -1);
        std::queue<int> que;
        level[s] = 0;
        que.push(s);
        while (!que.empty())
        {
            int v = que.front();
            que.pop();
            for (const auto &e : G[v])
            {
                if (e.cap > 0 && level[e.to] < 0)
                {
                    level[e.to] = level[v] + 1;
                    que.push(e.to);
                }
            }
        }
    }
    type dfs(int v, int t, type f)
    {
        if (v == t)
            return f;
        for (int &i = iter[v]; i < (int)G[v].size(); i++)
        {
            Edge &e = G[v][i];
            if (e.cap > 0 && level[v] < level[e.to])
            {
                type d = dfs(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;
    }

  public:
    Dinic(int _v) : V(_v), G(_v), level(_v), iter(_v) {}
    void add(int from, int to, int cap)
    {
        G[from].push_back(Edge{to, cap, (int)G[to].size()});
        G[to].push_back(Edge{from, 0, (int)G[from].size() - 1});
    }
    type maxFlow(int s, int t)
    {
        type ret = 0;
        while (true)
        {
            bfs(s);
            if (level[t] < 0)
                return ret;
            fill(iter.begin(), iter.end(), 0);
            type f;
            while ((f = dfs(s, t, INF)) > 0)
            {
                ret += f;
            }
        }
    }
};

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

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    int h, w;
    cin >> h >> w;
    vector<string> s(h);
    bool f = true;
    Dinic dinic(2 * h * w + 2);
    int S = 0, G = 2 * h * w + 1;
    for (int i = 0; i < h; i++)
    {
        cin >> s[i];
        for (int j = 0; j < w; j++)
        {
            int st = i * w + j + 1;
            int gt = i * w + j + 1 + h * w;
            if (s[i][j] == '.')
            {
                dinic.add(st, gt, 1);
                f = false;
            }
            else
            {
                dinic.add(st, gt, INF);
                dinic.add(S, gt, INF);
            }
            if (i == 0 || i == h - 1 || j == 0 || j == w - 1)
            {
                dinic.add(gt, G, INF);
            }
            for (int k = 0; k < 4; k++)
            {
                int ni = i + dx[k], nj = j + dy[k];
                if (ni < 0 || h <= ni || nj < 0 || w <= nj)
                    continue;
                int nst = ni * w + nj + 1;
                dinic.add(gt, nst, INF);
            }
        }
    }
    if (f)
    {
        cout << -1 << endl;
        return 0;
    }
    ll ret = dinic.maxFlow(S, G);
    cout << (ret < 100000 ? ret : -1) << endl;
}


Measured memory_bytes: 3200