#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

typedef int Weight;
struct Edge {
  int src;
  int dest;
  Weight weight;
  Edge(int src, int dest, Weight weight) : src(src), dest(dest), weight(weight) {;}
  bool operator<(const Edge &rhs) const {
    if (weight != rhs.weight) { return weight > rhs.weight; }
    if (src != rhs.src) { return src < rhs.src; }
    return dest < rhs.dest;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void printMatrix(const Matrix &matrix) {
  for (int y = 0; y < (int)matrix.size(); y++) {
    for (int x = 0; x < (int)matrix[y].size(); x++) {
      printf("%d ", matrix[y][x]);
    }
    puts("");
  }
}

void SccDfs(const Graph &g, int from, vector<int> &visit, vector<int> &st) {
  visit[from] = 1;
  for (Edges::const_iterator it = g[from].begin(); it != g[from].end(); it++) {
    if (visit[it->dest]) { continue; }
    SccDfs(g, it->dest, visit, st);
  }
  st.push_back(from);
}

vector<vector<int> > Scc(const Graph &g) {
  const int n = g.size();
  vector<vector<int> > ret;
  Graph revg(n);
  for (int i = 0; i < n; i++) {
    for (Edges::const_iterator it = g[i].begin(); it != g[i].end(); it++) {
      revg[it->dest].push_back(Edge(it->dest, i, it->weight));
    }
  }
  vector<int> st;
  vector<int> visit(n, 0);
  for (int i = 0; i < n; i++) {
    if (visit[i]) { continue; }
    SccDfs(g, i, visit, st);
  }
  visit = vector<int>(n, 0);
  for (int i = n - 1; i >= 0; i--) {
    int index = st[i];
    if (visit[index]) { continue; }
    vector<int> nret;
    SccDfs(revg, index, visit, nret);
    ret.push_back(nret);
  }
  return ret;
}

// select min weight edge
Graph SccGraph(const Graph &g) {
  vector<vector<int> > soc = Scc(g);
  const int n = g.size();
  const int m = soc.size();
  vector<int> mapto(n);
  for (int i = 0; i < (int)soc.size(); i++) {
    for (int j = 0; j < (int)soc[i].size(); j++) {
      mapto[soc[i][j]] = i;
    }
  }
  Graph ret(m);
  vector<int> indexs(m, -1);
  for (int from = 0; from < m; from++) {
    int e = 0;
    for (int i = 0; i < (int)soc[from].size(); i++) {
      for (Edges::const_iterator it = g[soc[from][i]].begin(); it != g[soc[from][i]].end(); it++) {
        int to = mapto[it->dest];
        if (from == to) { continue; } // loop back
        if (indexs[to] == -1) {
          ret[from].push_back(Edge(from, to, it->weight));
          indexs[to] = e++;
        } else {
          // select edge
          ret[from][indexs[to]].weight = min(ret[from][indexs[to]].weight, it->weight);
        }
      }
    }
    for (Edges::const_iterator it = ret[from].begin(); it != ret[from].end(); it++) {
      indexs[it->dest] = -1;
    }
  }
  return ret;
}

const ll MOD = 1000000007;
bool visit[1010];

ll dfs(const Graph &g, int from) {
  ll ret = 1;
  visit[from] = true;
  FORIT(it, g[from]) {
    assert(!visit[it->dest]);
    ret = (ret * dfs(g, it->dest)) % MOD;
  }
  ret++;
  return ret;
}

int main() {
  int n, m;
  scanf("%d %d", &n, &m);
  Graph g(n);
  REP(i, m) {
    int f, t;
    scanf("%d %d", &f, &t);
    f--; t--;
    g[t].push_back(Edge(t, f, 0));
  }
  g = SccGraph(g);
  MEMSET(visit, false);
  ll ans = 1;
  REP(i, g.size()) {
    if (visit[i]) { continue; }
    ans = (ans * dfs(g, i)) % MOD;
  }
  printf("%lld\n", ans);
}

Measured memory_bytes: 0