#include <bits/stdc++.h>
using namespace std;
const long long INF = 1e9;
long long gcd(long long a, long long b) { return (a ? gcd(b % a, a) : b); }
long long power(long long a, long long n) {
  long long p = 1;
  while (n > 0) {
    if (n % 2) {
      p = p * a;
    }
    n >>= 1;
    a *= a;
  }
  return p;
}
const int n_ = 1e5 + 10;
vector<long long> e[n_], re[n_], vc;
bool vis[n_];
int n, m, c[n_], cs[n_];
int noCycle(int v) {
  vis[v] = 1;
  int ret = (cs[c[v]] == 1);
  for (int(i) = 0; (i) < (e[v].size()); (i)++) {
    if (!vis[e[v][i]]) {
      ret = (ret & noCycle(e[v][i]));
    }
  }
  for (int(i) = 0; (i) < (re[v].size()); (i)++) {
    if (!vis[re[v][i]]) {
      ret = (ret & noCycle(re[v][i]));
    }
  }
  return ret;
}
void topolSort(int v) {
  vis[v] = 1;
  for (int(i) = 0; (i) < (e[v].size()); (i)++) {
    if (!vis[e[v][i]]) {
      topolSort(e[v][i]);
    }
  }
  vc.push_back(v);
}
void rdfs(int v, int cmp) {
  c[v] = cmp;
  vis[v] = 1;
  for (int(i) = 0; (i) < (re[v].size()); (i)++) {
    if (!vis[re[v][i]]) {
      rdfs(re[v][i], cmp);
    }
  }
}
void findStronglyConnectedCmp() {
  memset(vis, 0, sizeof(vis));
  vc.clear();
  for (int(i) = 0; (i) < (n); (i)++) {
    if (!vis[i]) topolSort(i);
  }
  memset(vis, 0, sizeof(vis));
  int cmp = 0;
  for (int(i) = (vc.size() - 1); (i) >= 0; (i)--) {
    if (!vis[vc[i]]) {
      rdfs(vc[i], cmp++);
    }
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  int u, v, ans;
  cin >> n >> m;
  ans = n;
  for (int(i) = 0; (i) < (m); (i)++) {
    cin >> u >> v;
    u--;
    v--;
    e[u].push_back(v);
    re[v].push_back(u);
  }
  findStronglyConnectedCmp();
  memset(cs, 0, sizeof(cs));
  for (int(i) = 0; (i) < (n); (i)++) {
    cs[c[i]]++;
  }
  memset(vis, 0, sizeof(vis));
  for (int(i) = 0; (i) < (n); (i)++) {
    if (!vis[i]) ans -= noCycle(i);
  }
  cout << ans;
  return 0;
}
