#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 100;
vector<int> g[N], rg[N], newG[N], tin(N), tout(N), used(N), ord, comp(N),
    cnt(N);
int cc = 0;
void dfs1(int v) {
  used[v] = 1;
  for (auto u : g[v]) {
    if (!used[u]) dfs1(u);
  }
  ord.push_back(v);
}
void dfs2(int v) {
  used[v] = 1;
  comp[v] = cc;
  cnt[cc]++;
  for (auto u : rg[v]) {
    if (!used[u]) dfs2(u);
  }
}
int ans = 0;
int dfs3(int v) {
  used[v] = 1;
  int ret = cnt[v] == 1;
  for (auto u : newG[v]) {
    if (used[u]) continue;
    ret = min(ret, dfs3(u));
  }
  return ret;
}
signed main() {
  ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    g[a].push_back(b);
    rg[b].push_back(a);
  }
  for (int i = 0; i < n; i++) {
    if (!used[i]) dfs1(i);
  }
  fill(used.begin(), used.end(), 0);
  reverse(ord.begin(), ord.end());
  for (auto x : ord) {
    if (!used[x]) {
      dfs2(x);
      cc++;
    }
  }
  fill(used.begin(), used.end(), 0);
  for (int v = 0; v < n; v++) {
    for (auto u : g[v]) {
      if (comp[v] != comp[u]) {
        newG[comp[v]].push_back(comp[u]);
        newG[comp[u]].push_back(comp[v]);
      }
    }
  }
  for (int i = 0; i < cc; i++) {
    sort(newG[i].begin(), newG[i].end());
    newG[i].resize(unique(newG[i].begin(), newG[i].end()) - newG[i].begin());
  }
  ans = n;
  for (int i = 0; i < cc; i++) {
    if (!used[i]) {
      ans -= dfs3(i);
    }
  }
  cout << ans << '\n';
}
