#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <complex>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <iomanip>
#include <assert.h>
#include <array>
#include <cstdio>
#include <cstring>
#include <random>
#include <functional>
#include <numeric>
#include <bitset>
#include <fstream>
 
using namespace std;
 
#define REP(i,a,b) for(int i=a;i<(int)b;i++)
#define rep(i,n) REP(i,0,n)
#define all(c) (c).begin(), (c).end()
#define zero(a) memset(a, 0, sizeof a)
#define minus(a) memset(a, -1, sizeof a)
#define watch(a) { cout << #a << " = " << a << endl; }
template<class T1, class T2> inline bool minimize(T1 &a, T2 b) { return b < a && (a = b, 1); }
template<class T1, class T2> inline bool maximize(T1 &a, T2 b) { return a < b && (a = b, 1); }
 
typedef long long ll;
int const inf = 1<<29;
 
constexpr int MOD = 1e9+7;
 
namespace graph { // not verified
 
constexpr int MaxV = 1010;
 
struct scc {
 
  int V = MaxV;
  vector<int> G[MaxV];
  vector<int> rG[MaxV];
  vector<int> vs;
  vector<bool> used;
  vector<int> comp;
  int SCCGraphSize;
 
  scc(): V(MaxV) { comp.resize(MaxV); }
  scc(int V_): V(V_) { comp.resize(MaxV); }
 
  void add_edge(int from, int to) {
    G[from].push_back(to);
    rG[to].push_back(from);
  }
 
  void dfs(int v) {
    used[v] = 1;
    for(auto e: G[v]) {
      if(!used[e]) dfs(e);
    }
    vs.push_back(v);
  }
 
  void rdfs(int v, int k) {
    used[v] = 1;
    comp[v] = k;
    for(auto e: rG[v]) {
      if(!used[e]) rdfs(e, k);
    }
  }
 
  void solve() {
    used.clear(); used.resize(MaxV);
    vs.clear();
    for(int i = 0; i < V; i++) {
      if(!used[i]) dfs(i);
    }
    used.clear(); used.resize(MaxV);
    int k = 0;
    for(int i = vs.size() - 1; i >= 0; i--) {
      if(!used[vs[i]]) rdfs(vs[i], k++);
    }
    SCCGraphSize = k;
  }
 
};
 
}
 
vector<vector<int>> tree;
ll dp[1010];
 
ll solve(int curr, int par) {
  ll& ret = dp[curr];
  if(ret + 1) return ret;
  ret = 1;
  for(auto e: tree[curr]) {
    if(e == par) continue;
    ret *= solve(e, curr);
    ret %= MOD;
  }
  (ret += 1) %= MOD;
  return ret;
}
 
int main() {
 
  int N, M; cin >> N >> M;
  graph::scc scc_graph(N);
  rep(i, M) {
    int S, D; cin >> S >> D; S --, D --;
    scc_graph.add_edge(S, D);
  }
 
  scc_graph.solve();
 
  auto& K = scc_graph.SCCGraphSize;
  auto& g = scc_graph.G;
  auto& comp = scc_graph.comp;
 
  tree.resize(K);
  int deg[1010] = {};
 
  rep(i, N) {
    for(auto e: g[i]) {
      if(comp[i] == comp[e]) continue;
      tree[comp[e]].push_back(comp[i]);
      deg[comp[i]] ++;
    }
  }
 
  rep(i, K) {
    sort(tree[i].begin(), tree[i].end());
    tree[i].erase(unique(tree[i].begin(), tree[i].end()), tree[i].end());
  }
 
  minus(dp);
 
  ll ans = 1;
 
  rep(i, K) if(deg[i] == 0 && dp[i] < 0) {
    ans *= solve(i, -1);
    ans %= MOD;
  }
 
  cout << ans << endl;
   
  return 0;
}