#include <bits/stdc++.h>
using namespace std;
struct Graph {
  int n;
  vector<vector<int>> adj;
  vector<vector<int>> rev;
  vector<bool> was;
  vector<int> color;
  vector<int> mark;
  Graph(int _n)
      : n(_n),
        adj(_n + 1),
        rev(_n + 1),
        was(_n + 1),
        color(_n + 1),
        mark(_n + 1) {}
  void addEdge(int a, int b) {
    adj[a].push_back(b);
    rev[b].push_back(a);
  }
  void clearWas() { fill(was.begin(), was.end(), false); }
  void colorize(int v, int col) {
    color[v] = col;
    for (int u : adj[v])
      if (color[u] == 0) colorize(u, col);
    for (int u : rev[v])
      if (color[u] == 0) colorize(u, col);
  }
  int countCompSize(int v) {
    int result = 1;
    was[v] = true;
    for (int u : adj[v])
      if (!was[u]) result += countCompSize(u);
    for (int u : rev[v])
      if (!was[u]) result += countCompSize(u);
    return result;
  }
  bool findCycle(int v) {
    was[v] = true;
    mark[v] = 2;
    for (int u : adj[v]) {
      if (mark[u] == 2) return true;
      if (mark[u] == 0 && findCycle(u)) return true;
    }
    mark[v] = 1;
    return false;
  }
};
struct DirectedGraph : Graph {
  vector<int> color;
  DirectedGraph(int _n) : Graph(_n), color(_n + 1) {}
  void addEdge(int a, int b) { adj[a].push_back(b); }
  void dfs(int v, vector<int> &order) {
    was[v] = true;
    for (int u : adj[v])
      if (!was[u]) dfs(u, order);
    order.push_back(v);
  }
  bool hasCycle(int v) {
    color[v] = 2;
    for (int u : adj[v]) {
      if (color[u] == 2) return true;
      if (color[u] == 0 && hasCycle(u)) return true;
    }
    color[v] = 1;
    return false;
  }
};
struct UndirectedGraph : Graph {
  UndirectedGraph(int _n) : Graph(_n) {}
  void addEdge(int a, int b) {
    adj[a].push_back(b);
    adj[b].push_back(a);
  }
  int countSize(int v) {
    int result = 1;
    was[v] = true;
    for (int u : adj[v])
      if (!was[u]) result += countSize(u);
    return result;
  }
};
int main() {
  ios_base::sync_with_stdio(false);
  int n, m;
  cin >> n >> m;
  Graph g(n);
  for (int i = 0; i < m; ++i) {
    int a, b;
    cin >> a >> b;
    g.addEdge(a, b);
  }
  int comps = 0;
  for (int v = 1; v <= n; ++v)
    if (g.color[v] == 0) g.colorize(v, ++comps);
  vector<int> compSize(comps + 1);
  for (int v = 1; v <= n; ++v)
    if (!g.was[v]) compSize[g.color[v]] += g.countCompSize(v);
  g.clearWas();
  vector<bool> hasCycle(comps + 1);
  for (int v = 1; v <= n; ++v)
    if (!g.was[v] && g.findCycle(v)) hasCycle[g.color[v]] = true;
  int result = 0;
  for (int c = 1; c <= comps; ++c)
    if (hasCycle[c])
      result += compSize[c];
    else
      result += compSize[c] - 1;
  cout << result << endl;
  return 0;
}
