#include <bits/stdc++.h>
using namespace std;
int n, m, a, b, scc_size[500005], ans;
int V;
const int MAX_V = 500005;
vector<int> G[MAX_V];
vector<int> rG[MAX_V];
vector<int> vs;
bool used[MAX_V];
int cmp[MAX_V];
void add_edge(int from, int to) {
  G[from].push_back(to);
  rG[to].push_back(from);
}
void dfs(int v) {
  used[v] = true;
  for (int i = 0; i < G[v].size(); i++) {
    if (!used[G[v][i]]) dfs(G[v][i]);
  }
  vs.push_back(v);
}
void rdfs(int v, int k) {
  used[v] = true;
  cmp[v] = k;
  for (int i = 0; i < rG[v].size(); i++) {
    if (!used[rG[v][i]]) rdfs(rG[v][i], k);
  }
}
int SCC() {
  memset(used, 0, sizeof(used));
  vs.clear();
  for (int v = 1; v <= V; v++) {
    if (!used[v]) dfs(v);
  }
  memset(used, 0, sizeof(used));
  int k = 0;
  for (int i = vs.size() - 1; i >= 0; i--) {
    if (!used[vs[i]]) rdfs(vs[i], k++);
  }
  return k;
}
int DFS(int v) {
  used[v] = true;
  int check = 0;
  if (scc_size[cmp[v]] == 1) check = 1;
  for (int i = 0; i < G[v].size(); i++) {
    if (!used[G[v][i]]) check &= DFS(G[v][i]);
  }
  for (int i = 0; i < rG[v].size(); i++) {
    if (!used[rG[v][i]]) check &= DFS(rG[v][i]);
  }
  return check;
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    cin >> a >> b;
    add_edge(a, b);
  }
  V = ans = n;
  SCC();
  for (int i = 1; i <= n; i++) {
    int group = cmp[i];
    scc_size[group]++;
  }
  memset(used, 0, sizeof(used));
  for (int i = 1; i <= n; i++) {
    if (!used[i]) {
      int cycle = DFS(i);
      ans -= cycle;
    }
  }
  cout << ans << endl;
  return 0;
}
