import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Main {

  static int H;
  static int W;
  private static void solve() {
    H = ni();
    W = ni();
    
    char[][] map = new char[H][];
    for (int i = 0; i < H; i ++) {
      map[i] = ns();
    }
    


    List<Edge> edges = new ArrayList<>();
    int src = W * H * 2;
    int sink = W * H * 2 + 1;

    int INF = 110000;
    int[][] DIR = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

    for (int i = 0; i < H; i ++) {
      for (int j = 0; j < W; j ++) {
        int in = j + W * i;
        int out = H * W + j + i * W;
        edges.add(new Edge(in, out, map[i][j] == 'X' ? INF : 1));
        
        if (i == 0 || i == H - 1 || j == 0 || j == W - 1) { 
          if (map[i][j] == 'X') {
            System.out.println(-1);
            return;
          } else {
            edges.add(new Edge(out, sink, INF));
          }
        }

        if (map[i][j] == 'X') {
          edges.add(new Edge(src, in, INF));
        }
        
        for (int[] d : DIR) {
          int ni = i + d[0];
          int nj = j + d[1];
          if (ni < 0 || ni >= H || nj < 0 || nj >= W) {
            continue;
          } else {
            int nin = nj + W * ni;
            edges.add(new Edge(out, nin, INF));
          }
        }
      }
    }

    long ret = maximumFlowDinicNoRec(compileWD(sink + 1, edges), src, sink);
    System.out.println(ret);
  }

  public static Edge[][] compileWD(int n, List<Edge> edges)
  {
      Edge[][] g = new Edge[n][];
      // cloning
      for(int i = edges.size()-1;i >= 0;i--){
          Edge origin = edges.get(i);
          Edge clone = new Edge(origin.to, origin.from, origin.capacity);
          clone.flow = origin.capacity;
          clone.complement = origin;
          clone.cloned = true;
          origin.complement = clone;
          edges.add(clone);
      }
      
      int[] p = new int[n];
      for(Edge e : edges)p[e.from]++;
      for(int i = 0;i < n;i++)g[i] = new Edge[p[i]];
      for(Edge e : edges)g[e.from][--p[e.from]] = e;
      return g;
  }
  
  public static class Edge
  {
      public int from, to;
      public int capacity;
      public int flow;
      public Edge complement;
      public boolean cloned;
      
      public Edge(int from, int to, int capacity) {
          this.from = from;
          this.to = to;
          this.capacity = capacity;
      }
  }
  
  public static long maximumFlowDinicNoRec(Edge[][] g, int source, int sink)
  {
      int n = g.length;
      int[] d = new int[n]; // distance
      int[] q = new int[n]; // queue for BFS
      long ret = 0;
      int[] stack = new int[n];
      long[] lefts = new long[n]; // left to flow
      long[] parflow = new long[n];
      int[] probe = new int[n]; // search pointer
      while(true){
          // BFS
          Arrays.fill(d, -1);
          q[0] = source;
          int r = 1;
          d[source] = 0;
          for(int v = 0;v < r;v++){
              int cur = q[v];
              for(Edge ne : g[cur]){
                  if(d[ne.to] == -1 && ne.capacity - ne.flow > 0) {
                      q[r++] = ne.to;
                      d[ne.to] = d[cur] + 1;
                  }
              }
          }
          if(d[sink] == -1)break;
          
          // DFS
          for(int i = 0;i < n;i++)probe[i] = g[i].length-1;
          int sp = 0;
          stack[sp] = source;
          lefts[sp] = Long.MAX_VALUE / 10;
          parflow[sp] = 0;
          sp++;
          long delta = 0;
          boolean down = true;
          while(sp > 0){
              int cur = stack[sp-1];
              long left = lefts[sp-1];
              if(cur == sink){
                  delta += left;
                  parflow[sp-1] = left;
                  sp--;
                  down = false;
                  continue;
              }
              if(!down){
                  if(parflow[sp] > 0){
                      lefts[sp-1] -= parflow[sp];
                      left = lefts[sp-1];
                      Edge ne = g[cur][probe[cur]];
                      ne.flow += parflow[sp];
                      ne.complement.flow -= parflow[sp];
                      parflow[sp-1] += parflow[sp];
                  }
                  if(left > 0)probe[cur]--;
              }
              if(left > 0 && probe[cur] >= 0){
                  down = true;
                  Edge ne = g[cur][probe[cur]];
                  if(d[ne.to] == d[cur]+1 && ne.capacity - ne.flow > 0){
                      lefts[sp] = Math.min(left, ne.capacity - ne.flow);
                      stack[sp] = ne.to;
                      parflow[sp] = 0;
                      sp++;
                  }else{
                      probe[cur]--;
                  }
              }else{
                  down = false;
                  sp--;
              }
          }
          ret += delta;
      }
      return ret;
  }
  
  public static void main(String[] args) {
    new Thread(null, new Runnable() {
      @Override
      public void run() {
        long start = System.currentTimeMillis();
        String debug = System.getProperty("debug");
        if (debug != null) {
          try {
            is = java.nio.file.Files.newInputStream(java.nio.file.Paths.get(debug));
          } catch (Exception e) {
            throw new RuntimeException(e);
          }
        }
        reader = new java.io.BufferedReader(new java.io.InputStreamReader(is), 32768);
        solve();
        out.flush();
        tr((System.currentTimeMillis() - start) + "ms");
      }
    }, "", 64000000).start();
  }

  private static java.io.InputStream is = System.in;
  private static java.io.PrintWriter out = new java.io.PrintWriter(System.out);
  private static java.util.StringTokenizer tokenizer = null;
  private static java.io.BufferedReader reader;

  public static String next() {
    while (tokenizer == null || !tokenizer.hasMoreTokens()) {
      try {
        tokenizer = new java.util.StringTokenizer(reader.readLine());
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
    return tokenizer.nextToken();
  }

  private static double nd() {
    return Double.parseDouble(next());
  }

  private static long nl() {
    return Long.parseLong(next());
  }

  private static int[] na(int n) {
    int[] a = new int[n];
    for (int i = 0; i < n; i++)
      a[i] = ni();
    return a;
  }

  private static char[] ns() {
    return next().toCharArray();
  }

  private static long[] nal(int n) {
    long[] a = new long[n];
    for (int i = 0; i < n; i++)
      a[i] = ni();
    return a;
  }

  private static int[][] ntable(int n, int m) {
    int[][] table = new int[n][m];
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        table[i][j] = ni();
      }
    }
    return table;
  }

  private static int[][] nlist(int n, int m) {
    int[][] table = new int[m][n];
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        table[j][i] = ni();
      }
    }
    return table;
  }

  private static int ni() {
    return Integer.parseInt(next());
  }

  private static void tr(Object... o) {
    if (is != System.in)
      System.out.println(java.util.Arrays.deepToString(o));
  }
}


Measured memory_bytes: 31072