#include <bits/stdc++.h>
using namespace std;
const double EPS = -1e8;
const double Pi = acos(-1);
bool inline equ(double a, double b) { return fabs(a - b) < EPS; }
const int MAXN = 100010;
struct DSJ {
  int mom[MAXN];
  void init(int x) {
    for (int i = 1; i <= x; i++) mom[i] = i;
  }
  int find(int x) { return mom[x] = mom[x] == x ? x : find(mom[x]); }
  void merge(int a, int b) { mom[find(a)] = find(b); }
};
int n, m;
vector<int> g[MAXN], rg[MAXN], vs;
bool vis[MAXN];
DSJ dsj;
int id[MAXN];
vector<int> scc[MAXN];
bool ok[MAXN];
int sz[MAXN];
void dfs(int u) {
  vis[u] = 1;
  for (auto v : g[u])
    if (!vis[v]) dfs(v);
  vs.push_back(u);
}
void rdfs(int u, int mk) {
  vis[u] = 1;
  id[u] = mk;
  scc[mk].push_back(u);
  for (auto v : rg[u])
    if (!vis[v]) rdfs(v, mk);
}
int main() {
  scanf("%d%d", &n, &m);
  dsj.init(n);
  for (int i = (1); i <= (m); i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    dsj.merge(u, v);
    g[u].push_back(v);
    rg[v].push_back(u);
  }
  for (int i = (1); i <= (n); i++) sz[dsj.find(i)]++;
  int cnt = 0;
  for (int i = (1); i <= (n); i++)
    if (!vis[i]) dfs(i);
  reverse((vs).begin(), (vs).end());
  fill(vis, vis + MAXN, 0);
  for (int u : vs)
    if (!vis[u]) {
      rdfs(u, ++cnt);
      if ((int)(scc[cnt]).size() > 1) ok[dsj.find(u)] = 1;
    }
  int ans = 0;
  for (int i = (1); i <= (n); i++)
    if (sz[i] > 0) {
      if (ok[i])
        ans += sz[i];
      else
        ans += sz[i] - 1;
    }
  printf("%d\n", ans);
}
