#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 10;
struct edge {
  int u, v, st, nt;
} e[MAXN * 2];
vector<int> lis;
int hd[MAXN], etot, used[MAXN], in[MAXN], u[MAXN], v[MAXN];
void addedge(int u, int v, int st) {
  e[etot].u = u;
  e[etot].v = v;
  e[etot].st = st;
  e[etot].nt = hd[u];
  hd[u] = etot++;
}
void dfs(int p) {
  used[p] = 1;
  lis.push_back(p);
  for (int i = hd[p]; ~i; i = e[i].nt) {
    if (used[e[i].v]) continue;
    dfs(e[i].v);
  }
}
queue<int> Q;
int topsort() {
  for (int i = 0; i < (int)lis.size(); i++)
    if (!in[lis[i]]) Q.push(lis[i]);
  int cnt = 0, u;
  for (; !Q.empty();) {
    cnt++;
    u = Q.front();
    Q.pop();
    for (int i = hd[u]; ~i; i = e[i].nt) {
      if (!e[i].st) continue;
      in[e[i].v]--;
      if (!in[e[i].v]) Q.push(e[i].v);
    }
  }
  return cnt == (int)lis.size();
}
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  etot = 0;
  memset(hd, -1, sizeof(hd));
  for (int i = 0; i < m; i++) {
    scanf("%d%d", u + i, v + i);
    addedge(u[i], v[i], 1);
    addedge(v[i], u[i], 0);
    in[v[i]]++;
  }
  int ans = 0;
  for (int i = 1; i < n + 1; i++) {
    lis.clear();
    if (!used[i]) dfs(i);
    if ((int)lis.size() == 0) continue;
    ans += (int)lis.size() - topsort();
  }
  printf("%d\n", ans);
  return 0;
}
