#include <bits/stdc++.h>
using namespace std;
const int Max_N(300050);
const int Max_M(300050);
namespace io {
const int SIZE = (1 << 24) + 1;
char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c,
                                       qu[55];
int f, qr;
inline void flush() {
  fwrite(obuf, 1, oS - obuf, stdout);
  oS = obuf;
}
inline void putc(char x) {
  *oS++ = x;
  if (oS == oT) flush();
}
template <class I>
inline void gi(I &x) {
  for (f = 1, c = (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, SIZE, stdin),
                              (iS == iT ? EOF : *iS++))
                            : *iS++);
       c < '0' || c > '9';
       c = (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, SIZE, stdin),
                       (iS == iT ? EOF : *iS++))
                     : *iS++))
    if (c == '-') f = -1;
  for (x = 0; c <= '9' && c >= '0';
       c = (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, SIZE, stdin),
                       (iS == iT ? EOF : *iS++))
                     : *iS++))
    x = x * 10 + (c & 15);
  x *= f;
}
template <class I>
inline void print(I x) {
  if (!x) putc('0');
  if (x < 0) putc('-'), x = -x;
  while (x) qu[++qr] = x % 10 + '0', x /= 10;
  while (qr) putc(qu[qr--]);
}
struct Flusher_ {
  ~Flusher_() { flush(); }
} io_flusher_;
}  // namespace io
using io::gi;
using io::print;
using io::putc;
int N, M, Q[Max_N], Sum[Max_N];
struct G {
  int Head[Max_N], To[Max_M], Next[Max_M], In[Max_N], F[Max_N], Suf[Max_N],
      Cnt[Max_N];
  vector<int> V[Max_N];
  set<int> G[Max_N];
  inline void Add_Edge(int tot, int s, int t) {
    To[tot] = t, Next[tot] = Head[s], Head[s] = tot, ++In[t];
  }
  void toposort() {
    Q[0] = 0;
    for (int u = 1; u <= N; ++u)
      if (In[u] == 0) F[Q[++Q[0]] = u] = 1;
    for (int ft = 0, u; ++ft <= Q[0];) {
      u = Q[ft], V[F[u]].push_back(u);
      for (int i = Head[u], v; i; i = Next[i]) {
        F[v = To[i]] = F[u] + 1;
        if ((--In[v]) == 0) Q[++Q[0]] = v;
      }
    }
  }
  void insert(int s, int t) {
    if (G[t].size() == 1) --Cnt[*G[t].begin()];
    G[t].insert(s);
    if (G[t].size() == 1) ++Cnt[*G[t].begin()];
  }
  void erase(int s, int t) {
    if (G[t].size() == 1) --Cnt[*G[t].begin()];
    G[t].erase(s);
    if (G[t].size() == 1) ++Cnt[*G[t].begin()];
  }
  void insert(int s) {
    for (int i = Head[s]; i; i = Next[i]) insert(s, To[i]);
  }
  void erase(int s) {
    for (int i = Head[s]; i; i = Next[i]) erase(s, To[i]);
  }
  void work() {
    for (int s = 1; s <= N; ++s) insert(s);
    for (int i = N; i >= 1; --i) Suf[i] = V[i].size() + Suf[i + 1];
    set<int> S;
    for (int x = 1; V[x].size(); ++x) {
      S.clear();
      for (int j = 0; j < V[x + 1].size(); ++j) S.insert(V[x + 1][j]);
      for (int j = 0; j < V[x].size(); ++j) erase(V[x][j]);
      for (int j = 0, u; j < V[x].size(); ++j) {
        insert(u = V[x][j]);
        for (int i = Head[u], v; i; i = Next[i])
          if (F[v = To[i]] == F[u] + 1) S.erase(v);
        if (S.size() >= 2)
          Sum[u] += -N;
        else if (S.empty())
          Sum[u] += Suf[x + 1];
        else if (Cnt[*S.begin()])
          Sum[u] += -N;
        else
          Sum[u] += Suf[x + 1] - 1;
        for (int i = Head[u], v; i; i = Next[i])
          if (F[v = To[i]] == F[u] + 1) S.insert(v);
        erase(u);
      }
    }
  }
};
G A, B;
int main() {
  gi(N), gi(M);
  for (int i = 1, s, t; i <= M; ++i)
    gi(s), gi(t), A.Add_Edge(i, s, t), B.Add_Edge(i, t, s);
  A.toposort(), B.toposort(), A.work(), B.work();
  int Ans = 0;
  for (int u = 1; u <= N; ++u) Ans += (Sum[u] >= N - 2);
  printf("%d", Ans);
  return 0;
}
