import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.*;

public class B_Monopole_Magnets {
	
	static int N;
	static int M;
	
	public static void main(String[] args) {
		MyScanner sc = new MyScanner();
	    PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
	    N = sc.nextInt();
	    M = sc.nextInt();
	    
	    //1 = black and 0 = white
	    int[][] table = new int[N][M];
	    for(int i = 0; i < N; i++) {
	    	String row = sc.nextLine();
	    	for(int j = 0; j < M; j++) {
	    		if(row.charAt(j) == '#')
	    			table[i][j] = 1;
	    		else 
	    			table[i][j] = 0;
	    	}
	    }
	    
	    //Ensure each row and col only contains one contiguous section - O(nm)
	    boolean impossible = false;
	    //Check rows
	    for(int r = 0; r < N; r++) {
	    	boolean section_found = false;
	    	for(int c = 0; c < M; c++) {
	    		if(section_found && table[r][c] == 1 && (c != 0 && table[r][c - 1] == 0)) {
	    			impossible = true;
	    		}
	    		if(table[r][c] == 1)
	    			section_found = true;
	    	}
	    }
	    //Check cols
	    for(int c = 0; c < M; c++) {
	    	boolean section_found = false;
	    	for(int r = 0; r < N; r++) {
	    		if(section_found && table[r][c] == 1 && (r != 0 && table[r - 1][c] == 0)) {
	    			impossible = true;
	    		}
	    		if(table[r][c] == 1)
	    			section_found = true;
	    	}
	    }    
	    
	    //Count contiguous regions and return answer - flood fill w/ disjoint set union
	    //Hashsets contain rows and cols that we need to put an S magnet in
	    HashSet<Integer> rows_empty = new HashSet<>();
	    HashSet<Integer> cols_empty = new HashSet<>();
	    for(int i = 0; i < N; i++) rows_empty.add(i);
	    for(int i = 0; i < M; i++) cols_empty.add(i);
	    
	    for(int r = 0; r < N; r++) {
	    	for(int c = 0; c < M; c++) {
	    		//If pos is black
	    		if(table[r][c] == 1) {
	    			rows_empty.remove(r);
	    			cols_empty.remove(c);
	    		}
	    	}
	    }
	    
	    if(rows_empty.size() == 0 && cols_empty.size() > 0)
	    	impossible = true;
	    if(cols_empty.size() == 0 && rows_empty.size() > 0)
	    	impossible = true;
	    
	    int cnt = 0;
	    
	    boolean[][] visited = new boolean[N][M];
	    for(int r = 0; r < N; r++) {
	    	for(int c = 0; c < M; c++) {
	    		if(visited[r][c] == true || table[r][c] == 0) continue;
	    		
	    		cnt++;
	    	    Queue<Pair> toVisit = new LinkedList<Pair>();

	    	    toVisit.add(new Pair(r, c));
	    	    visited[r][c] = true;
	    	    while(!toVisit.isEmpty()) {
	    	    	Pair curr = toVisit.poll();
	    	    	int curr_r = curr.x;
	    	    	int curr_c = curr.y;
	    	    	
	    	    	//4 directional flood fill
	    	    	if(inBounds(curr_r, curr_c + 1) && !visited[curr_r][curr_c + 1] 
	    	    			&& table[curr_r][curr_c + 1] == 1) {
	    	    		visited[curr_r][curr_c + 1] = true;
	    	    		toVisit.add(new Pair(curr_r, curr_c + 1));
	    	    	}
	    	    	if(inBounds(curr_r + 1, curr_c) && !visited[curr_r + 1][curr_c] 
	    	    			&& table[curr_r + 1][curr_c] == 1) {
	    	    		visited[curr_r + 1][curr_c] = true;
	    	    		toVisit.add(new Pair(curr_r + 1, curr_c));
	    	    	}
	    	    	if(inBounds(curr_r, curr_c - 1) && !visited[curr_r][curr_c - 1] 
	    	    			&& table[curr_r][curr_c - 1] == 1) {
	    	    		visited[curr_r][curr_c - 1] = true;
	    	    		toVisit.add(new Pair(curr_r, curr_c - 1));
	    	    	}
	    	    	if(inBounds(curr_r - 1, curr_c) && !visited[curr_r - 1][curr_c] 
	    	    			&& table[curr_r - 1][curr_c] == 1) {
	    	    		visited[curr_r - 1][curr_c] = true;
	    	    		toVisit.add(new Pair(curr_r - 1, curr_c));
	    	    	}
	    	    }
	    	}
	    }
	    
	    if(impossible)
	    	out.println(-1);
	    else
	    	out.println(cnt);
	    
	    out.close();
	}
	
	public static boolean inBounds(int r, int c) {
		if(r < 0 || r >= N) return false;
		if(c < 0 || c >= M) return false;
		
		return true;
	}
	
	static class Pair {
		int x = 0;
		int y = 0;
		
		Pair(int x, int y) {
			this.x = x;
			this.y = y;
		}
	}
	
	static class Node {
		int rank;
		int data;
		Node parent = null;
		
		Node(int rank, int data) {
			this.rank = rank;
			this.data = data;
		}
	}
	
	static class DisjointSet {	
		private HashMap<Integer, Node> map = new HashMap<>();
		
		public void makeSet(int data) {
			Node n = new Node(0, data);
			map.put(data, n);
		}
		
		public int findSet(int elem) {
			Node curr = map.get(elem);
			if(curr.parent == null)
				return elem;
			
			curr.parent = map.get(findSet(curr.parent.data));
			return curr.parent.data;
		}
		
		public void union(int a, int b) {
			int rep1 = findSet(a);
			int rep2 = findSet(b);
			
			if(rep1 == rep2) return;
			
			if(map.get(rep1).rank == map.get(rep2).rank) {
				map.get(rep2).parent = map.get(rep1);
				map.get(rep1).rank++;
			}
			
			if(map.get(rep1).rank > map.get(rep2).rank) {
				map.get(rep2).parent = map.get(rep1);
			}else {
				map.get(rep1).parent = map.get(rep2);
			}
		}
	}
	
	private static class MyScanner {
		BufferedReader br;
	    StringTokenizer st;
	 
	    public MyScanner() {
	       br = new BufferedReader(new InputStreamReader(System.in));
	    }
	 
	    String next() {
	    	while (st == null || !st.hasMoreElements()) {
	    		try {
	    			st = new StringTokenizer(br.readLine());
	            	
	    		} catch (IOException e) {
	    			e.printStackTrace();
	            }
	          }
	    	return st.nextToken();
	   }
	 
	   int nextInt() {
		   return Integer.parseInt(next());
	   }
	 
	   long nextLong() {
		   return Long.parseLong(next());
	   }
	 
	   double nextDouble() {
		   return Double.parseDouble(next());
	   }
	 
	   String nextLine(){
		   String str = "";
		   try {
			   str = br.readLine();
		   } catch (IOException e) {
			   e.printStackTrace();
		   }
		   return str;
	   }
	}
}