#include <bits/stdc++.h>
using namespace std;
struct DisjointSet {
  vector<int> label;
  DisjointSet(int n) { label.assign(n, -1); }
  int get(int u) { return label[u] < 0 ? u : label[u] = get(label[u]); }
  void join(int u, int v) {
    u = get(u);
    v = get(v);
    if (u == v) return;
    if (label[u] < label[v]) swap(u, v);
    label[v] += label[u];
    label[u] = v;
  }
};
const int N = (int)1e5;
vector<int> vertices[N];
vector<int> graph[N];
bool visited[N];
int topo[N];
int counter;
void dfs(int u) {
  if (visited[u]) return;
  visited[u] = true;
  for (int v : graph[u]) dfs(v);
  topo[u] = --counter;
}
int main() {
  ios::sync_with_stdio(false);
  int n;
  cin >> n;
  int m;
  cin >> m;
  DisjointSet ds(n);
  for (int i = 0; i < m; ++i) {
    int u;
    cin >> u;
    --u;
    int v;
    cin >> v;
    --v;
    graph[u].push_back(v);
    ds.join(u, v);
  }
  for (int u = 0; u < n; ++u) {
    vertices[ds.get(u)].push_back(u);
    dfs(u);
  }
  counter = n;
  int result = 0;
  for (int i = 0; i < n; ++i)
    if (!vertices[i].empty()) {
      bool isDAG = true;
      for (int u : vertices[i]) {
        for (int v : graph[u]) {
          isDAG &= topo[u] < topo[v];
        }
      }
      result += vertices[i].size() - (isDAG ? 1 : 0);
    }
  cout << result << endl;
  return 0;
}
