#include <bits/stdc++.h>
using namespace std;
vector<vector<int>> adj, radj;
int n, m;
vector<int> vis;
vector<int> belongto;
vector<int> sz;
vector<pair<int, int>> edges;
stack<int> s;
int itr;
void dfs(int pos) {
  vis[pos] = 1;
  for (int &nxt : adj[pos])
    if (!vis[nxt]) dfs(nxt);
  s.push(pos);
}
int dfs2(int pos) {
  int ret = 1;
  vis[pos] = 1;
  belongto[pos] = itr;
  for (int &nxt : radj[pos])
    if (!vis[nxt]) ret += dfs2(nxt);
  return ret;
}
vector<int> par;
vector<int> ada, sz2;
int caripar(int x) {
  if (par[x] == x) return x;
  return par[x] = caripar(par[x]);
}
int32_t main() {
  ios::sync_with_stdio(false);
  cin.tie(NULL);
  cin >> n >> m;
  adj.resize(n);
  radj.resize(n);
  vis = vector<int>(n, 0);
  belongto.resize(n);
  itr = 0;
  edges.resize(m);
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    u--;
    v--;
    edges[i] = {u, v};
    adj[u].push_back(v);
    radj[v].push_back(u);
  }
  for (int i = 0; i < n; i++) {
    if (!vis[i]) dfs(i);
  }
  vis = vector<int>(n, 0);
  while (!s.empty()) {
    if (!vis[s.top()]) {
      sz.push_back(dfs2(s.top()));
      itr++;
    }
    s.pop();
  }
  par.resize(n);
  for (int i = 0; i < n; i++) par[i] = i;
  sz2 = vector<int>(n, 1);
  ada.resize(n);
  for (int i = 0; i < n; i++) ada[i] = (sz[belongto[i]] > 1 ? 1 : 0);
  vis = vector<int>(n, 0);
  for (int i = 0; i < m; i++) {
    int u, v;
    u = edges[i].first, v = edges[i].second;
    if (caripar(u) == caripar(v)) continue;
    sz2[caripar(v)] += sz2[caripar(u)];
    ada[caripar(v)] |= ada[caripar(u)];
    par[caripar(u)] = caripar(v);
  }
  int ans = 0;
  for (int i = 0; i < n; i++) {
    if (vis[caripar(i)]) continue;
    vis[caripar(i)] = 1;
    ans += sz2[caripar(i)] + ada[caripar(i)] - 1;
  }
  cout << ans << '\n';
}
