#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int n, m, iTime;
stack<int> st;
vector<bool> inSt;
vector<int> disc, low, szScc, inScc;
vector<vector<int> > gr, adj;
void dfs(int u) {
  disc[u] = low[u] = ++iTime;
  st.emplace(u);
  inSt[u] = true;
  for (int v : gr[u]) {
    if (!disc[v]) {
      dfs(v);
      low[u] = min(low[u], low[v]);
    } else if (inSt[v])
      low[u] = min(low[u], disc[v]);
  }
  if (disc[u] == low[u]) {
    szScc.emplace_back(0);
    while (st.top() != u) {
      ++szScc.back();
      inScc[st.top()] = ((int)(szScc).size()) - 1;
      inSt[st.top()] = false;
      st.pop();
    }
    ++szScc.back();
    inScc[st.top()] = ((int)(szScc).size()) - 1;
    inSt[st.top()] = false;
    st.pop();
  }
}
void dfs2(int u, bool& tmp, int& cnt) {
  disc[u] = 1;
  ++cnt;
  if (szScc[inScc[u]] > 1) tmp = false;
  for (int v : adj[u])
    if (!disc[v]) dfs2(v, tmp, cnt);
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> m;
  gr.assign(n, {});
  adj.assign(n, {});
  while (m--) {
    int u, v;
    cin >> u >> v;
    --u;
    --v;
    gr[u].emplace_back(v);
    adj[u].emplace_back(v);
    adj[v].emplace_back(u);
  }
  disc.assign(n, 0);
  low.assign(n, 0);
  inSt.assign(n, false);
  inScc.assign(n, -1);
  for (int u = 0; u < n; ++u)
    if (!disc[u]) dfs(u);
  int ans = 0;
  disc.assign(n, 0);
  for (int u = 0; u < n; ++u)
    if (!disc[u]) {
      bool tmp = true;
      int nV = 0;
      dfs2(u, tmp, nV);
      ans += nV - tmp;
    }
  cout << ans << '\n';
  return 0;
}
