#include <bits/stdc++.h>

#define fi first
#define se second
#define DB double
#define U unsigned
#define P std::pair
#define LL long long
#define LD long double
#define pb emplace_back
#define MP std::make_pair
#define SZ(x) ((int)x.size())
#define all(x) x.begin(),x.end()
#define CLR(i,a) memset(i,a,sizeof(i))
#define FOR(i,a,b) for(int i = a;i <= b;++i)
#define ROF(i,a,b) for(int i = a;i >= b;--i)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl

const int MAXN = 1000+5;
int f[MAXN<<1];
inline int find(int x){
	return x == f[x] ? x : f[x] = find(f[x]);
}

inline void merge(int x,int y){
	x = find(x);y = find(y);
	if(x == y) return;
	f[x] = y;
}

char str[MAXN];
int n,m;

int main(){
	scanf("%d%d",&n,&m);
	FOR(i,1,n+m) f[i] = i;
	FOR(i,1,n){
		scanf("%s",str+1);
		FOR(j,1,m){
			if(str[j] == '#') merge(i,j+n);
		}
	}
	merge(1,n+1);
	merge(1,n+m);
	merge(n,n+1);
	merge(n,n+m);
	std::vector<int> v1,v2;
	FOR(i,1,n) v1.pb(find(i));
	FOR(i,n+1,n+m) v2.pb(find(i));
	std::sort(all(v1));v1.erase(std::unique(all(v1)),v1.end());
	std::sort(all(v2));v2.erase(std::unique(all(v2)),v2.end());
	int ans = std::min(SZ(v1),SZ(v2))-1;
	printf("%d\n",ans);
	return 0;
}
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vl = vector<ll>;
using vvl = vector<vl>;
	
#define MOD 1000000007LL
#define INF 1LL << 60
#define rep(i,start,end) for(ll i = start; i < end; i++)
#define per(i,end,start) for(ll i = start-1; i >= end; i--)

ll N, M;
vvl G;
ll ct;
vl seen;

void dfs(ll n) {
  seen[n] = 1;
  ct++;
  
  for(auto next : G[n]) {
    if(seen[next] != -1) continue;
    dfs(next);
  }
}

int main() {
  cin >> N >> M;
  G.assign(N+1, vl());
  
  rep(i, 0, M) {
    ll a, b; cin >> a >> b;
    G[a].push_back(b);
  }
  ll res = 0;
  rep(i, 1, N+1) {
    ct = 0;
    seen.assign(N+1, -1);
    dfs(i);
    res += ct;
  }
  cout << res;
}