#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <utility>
#include <tuple>
#include <queue>
using namespace std;
using ll = long long int;

struct Edge {
  int to, cost;
  Edge(int a, int b) : to(a), cost(b) {}
};

struct GraphSCC {
  const int n;
  vector<int> isthrough;
  vector<int> vs, cmp;
  vector< vector< Edge > > G, rG;
  vector< vector<int> > H;

  GraphSCC(vector< vector< Edge > > &g) :
    n(g.size()), isthrough(g.size(), false), cmp(g.size(), 0), G(g), rG(g.size()) {
    // fprintf(stderr, "n = %d\n", n);
    for(int i=0; i<n; i++) for(int j=0; j<G[i].size(); j++)
                             rG[ G[i][j].to ].push_back(Edge(i, G[i][j].cost));
  }

  void SCC_dfsone(int cur) {
    isthrough[cur] = true;
    for(int i=0; i<G[cur].size(); i++) {
      if(!isthrough[G[cur][i].to]) {
        SCC_dfsone(G[cur][i].to);
      }
    }
    vs.push_back(cur);
  }

  void SCC_dfstwo(vector<int> &vec, int cur, int k) {
    cmp[cur] = k;
    isthrough[cur] = true;
    vec.push_back(cur);
    for(int i=0; i<rG[cur].size(); i++) {
      if(!isthrough[rG[cur][i].to]) {
        SCC_dfstwo(vec, rG[cur][i].to, k);
      }
    }
  }
  pair< vector<int>, int > scc() {
    for(int i=0; i<n; i++) {
      if(!isthrough[i]) SCC_dfsone(i);
    }

    fill(isthrough.begin(), isthrough.end(), false);
    reverse(vs.begin(), vs.end());
    int k = 0; vector< vector<int> > S;

    for(int i=0; i<vs.size(); i++) {
      if(!isthrough[vs[i]]) {
        S.push_back(vector<int>());
        SCC_dfstwo(S.back(), vs[i], k++);
      }
    }
    
    H.resize(k);
    fill(isthrough.begin(), isthrough.end(), false);
    for(int i=0; i<k; i++) {
      for(int j=0; j<S[i].size(); j++) {
        int v = S[i][j];
        for(int x=0; x<G[v].size(); x++) {
          int u = G[v][x].to;
          if(isthrough[cmp[u]] || cmp[v] == cmp[u]) continue;
          isthrough[ cmp[u] ] = true;
          H[ cmp[v] ].push_back(cmp[u]);
        }
      }
      for(int j=0; j<H[i].size(); j++) isthrough[ H[i][j] ] = false;
    }
    return make_pair(cmp, k);
  }
};

ll dp[1010][2];
const ll MOD = 1000000007;
using Graph = vector< vector< Edge > >;

int main() {
  int N, M; cin >> N >> M;
  Graph G(N);
  for(int i=0; i<M; i++) {
    int u, v; cin >> u >> v;
    u--; v--;
    G[u].push_back(Edge(v, 1));
  }

  GraphSCC compG(G);
  compG.scc();
  auto H = compG.H;

  N = H.size();
  vector<int> indeg(N), outdeg(N), visited(N), cnt(N);
  for(int i=0; i<N; i++) {
    for(auto e : H[i]) {
      indeg[e]++;
      outdeg[i]++;
    }
    dp[i][0] = dp[i][1] = 1;
  }
  
  ll ans = 1;
  queue<int> que;
  for(int i=0; i<N; i++) {
    if(indeg[i] == 0) {
      que.push(i);
      visited[i] = true;
      dp[i][0] = dp[i][1] = 1;
    }
  }

  while(que.size()) {
    int cur = que.front(); que.pop();
    for(auto to : H[cur]) {
      (dp[to][0] *= dp[cur][0]) %= MOD;
      (dp[to][1] *= (dp[cur][0] + dp[cur][1])) %= MOD;
      cnt[to]++;
      if(indeg[to] == cnt[to]) {
        que.push(to);
      }
    }
    if(outdeg[cur] == 0) {
      (ans *= (dp[cur][0] + dp[cur][1])) %= MOD;
    }
  }

  /*
  cout << N << endl;
  for(int i=0; i<N; i++) {
    fprintf(stderr, "dp[%d][0] = %lld, dp[%d][1] = %lld\n", i, dp[i][0], i, dp[i][1]);
  }
  */

  cout << ans << endl;
  return 0;
}



Measured memory_bytes: 3448