#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 1000;
const long long infinite = 1000 * 1000 * 1000 + 7;
const long long INFINF = 9000372036854;
int n, m;
vector<vector<long long> > gBFS;
vector<vector<long long> > g;
vector<bool> usedBFS;
vector<long long> used;
vector<long long> vComp;
void bfs(int i) {
  queue<long long> q;
  q.push(i);
  usedBFS[i] = true;
  while (!q.empty()) {
    int v = q.front();
    q.pop();
    for (int j = 0; j < gBFS[v].size(); ++j) {
      int to = gBFS[v][j];
      if (!usedBFS[to]) {
        q.push(to);
        usedBFS[to] = true;
      }
    }
  }
}
long long countCycles = 0;
bool dfs(int x) {
  for (int y : g[x]) {
    if (!used[y]) {
      used[y] = 1;
      if (dfs(y)) return 1;
    } else if (used[y] == 1)
      return 1;
  }
  used[x] = 2;
  return 0;
}
vector<bool> usedDFS;
set<int> path;
void dfsN(int v) {
  usedDFS[v] = 1;
  for (int i = 0; i < gBFS[v].size(); ++i)
    if (!usedDFS[gBFS[v][i]]) {
      path.insert(gBFS[v][i]);
      dfsN(gBFS[v][i]);
    }
}
int main() {
  cin >> n >> m;
  usedBFS.resize(n + 1, false);
  gBFS.resize(n + 1);
  g.resize(n + 1);
  used.resize(n + 1, 0);
  for (int i = 0; i < m; ++i) {
    int x, y;
    cin >> x >> y;
    gBFS[x].push_back(y);
    gBFS[y].push_back(x);
    g[x].push_back(y);
  }
  int countOfComponents = 0;
  for (int i = 1; i <= n; ++i) {
    if (!usedBFS[i]) {
      bfs(i);
      countOfComponents++;
      vComp.push_back(i);
    }
  }
  for (int i = 0; i < vComp.size(); ++i) {
    path.clear();
    usedDFS.clear();
    usedDFS.resize(n + 1);
    dfsN(vComp[i]);
    for (set<int>::iterator it = path.begin(); it != path.end(); ++it) {
      if (dfs(*it)) {
        ++countCycles;
        break;
      }
    }
  }
  cout << n - countOfComponents + countCycles;
  return 0;
}
