#include <bits/stdc++.h>
using namespace std;
int const p = 1e9 + 7;
int mod(int x) { return x >= p ? x - p : x; }
int n1, n2, fac[1000005], x[105], y[105], z[105], fa[105], siz[105],
    f[2][1 << 25 | 5], siz2[105], ans[105], id[105], tmp[105], as[105],
    g[105][2][105];
bool tag[105], d[105];
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
vector<int> vl[105], vr[105], e[105];
vector<pair<int, int>> to[105], to2[105];
void work1(int root) {
  if (vl[root].size() < vr[root].size()) swap(vl[root], vr[root]);
  int m = vl[root].size(), w = vr[root].size();
  for (int i = 0; i <= 1; i++)
    for (int j = 0; j < (1 << w); j++) f[i][j] = 0;
  f[0][0] = 1;
  for (int i = 0; i < vr[root].size(); i++) id[vr[root][i]] = i;
  for (int i = 0, v = 0; i < m; i++, v ^= 1) {
    for (int j = 0; j < (1 << w); j++) f[v ^ 1][j] = 0;
    for (int j = 0; j < (1 << w); j++)
      if (f[v][j]) {
        f[v ^ 1][j] = mod(f[v ^ 1][j] + f[v][j]);
        for (auto tar : to[vl[root][i]]) {
          if (!(j & (1 << id[tar.first])))
            f[v ^ 1][j | (1 << id[tar.first])] =
                (f[v ^ 1][j | (1 << id[tar.first])] +
                 1ll * f[v][j] * tar.second) %
                p;
        }
      }
  }
  for (int i = 0, tmp; i < (1 << w); i++)
    if (f[m & 1][i])
      tmp = __builtin_popcount(i), ans[tmp] = mod(ans[tmp] + f[m & 1][i]);
}
void dfs(int x, int fa) {
  static int tmp[2][105];
  memset(g[x], 0, sizeof(g[x]));
  g[x][d[x]][0] = siz[x] = 1;
  for (auto [tar, w] : to2[x]) {
    if (tar == fa) continue;
    dfs(tar, x);
    memset(tmp, 0, sizeof(tmp));
    for (int i = 0; i <= siz[x]; i++)
      for (int j = 0; j <= siz[tar]; j++)
        tmp[0][i + j] =
            (tmp[0][i + j] + 1ll * g[x][0][i] * (g[tar][0][j] + g[tar][1][j])) %
            p,
                   tmp[1][i + j] =
                       (tmp[1][i + j] +
                        1ll * g[x][1][i] * (g[tar][1][j] + g[tar][0][j])) %
                       p,
                   tmp[1][i + j + 1] =
                       (tmp[1][i + j + 1] +
                        1ll * g[x][0][i] * g[tar][0][j] % p * w) %
                       p;
    memcpy(g[x], tmp, sizeof(g[x]));
    siz[x] += siz[tar];
  }
}
void work2(int root) {
  int m = e[root].size();
  for (int i = 0, t; i < (1 << m); i++) {
    memset(d, 0, sizeof(d));
    int now = 1;
    for (int j = 0; j < m; j++)
      if (i & (1 << j)) {
        if (d[x[e[root][j]]] || d[y[e[root][j]] + n1]) goto nxt;
        d[x[e[root][j]]] = d[y[e[root][j]] + n1] = 1;
        now = 1ll * now * z[e[root][j]] % p;
      }
    dfs(root, 0);
    t = __builtin_popcount(i);
    for (int j = 0; j <= siz[root]; j++)
      ans[j + t] =
          (ans[j + t] + 1ll * now * (g[root][0][j] + g[root][1][j])) % p;
  nxt:;
  }
}
int main() {
  int n, k;
  vector<int> vx, vy;
  scanf("%d%d", &n, &k);
  fac[0] = 1;
  for (int i = 1; i <= n; i++) fac[i] = 1ll * fac[i - 1] * i % p;
  for (int i = 1; i <= k; i++) {
    scanf("%d%d%d", &x[i], &y[i], &z[i]);
    z[i] = mod(z[i] - 1 + p);
    if (!z[i]) {
      i--;
      k--;
      continue;
    }
    vx.push_back(x[i]), vy.push_back(y[i]);
  }
  sort(vx.begin(), vx.end()), vx.erase(unique(vx.begin(), vx.end()), vx.end()),
      sort(vy.begin(), vy.end()),
      vy.erase(unique(vy.begin(), vy.end()), vy.end());
  n1 = vx.size(), n2 = vy.size();
  for (int i = 1; i <= n1 + n2; i++) fa[i] = i, siz[i] = 1;
  for (int i = 1; i <= k; i++) {
    x[i] = lower_bound(vx.begin(), vx.end(), x[i]) - vx.begin() + 1,
    y[i] = lower_bound(vy.begin(), vy.end(), y[i]) - vy.begin() + 1;
    int fx = find(x[i]), fy = find(y[i] + n1);
    if (fx != fy)
      fa[fy] = fx, siz[fx] += siz[fy], to2[x[i]].push_back({y[i] + n1, z[i]}),
      to2[y[i] + n1].push_back({x[i], z[i]});
    else
      tag[i] = 1;
  }
  for (int i = 1; i <= k; i++) {
    to[x[i]].push_back({y[i] + n1, z[i]}),
        to[y[i] + n1].push_back({x[i], z[i]}), siz2[find(x[i])]++;
    if (tag[i]) e[find(x[i])].push_back(i);
  }
  for (int i = 1; i <= n1; i++) vl[find(i)].push_back(i);
  for (int i = n1 + 1; i <= n1 + n2; i++) vr[find(i)].push_back(i);
  as[0] = 1;
  for (int i = 1; i <= n1 + n2; i++)
    if (fa[i] == i && siz[i] > 1) {
      memset(ans, 0, sizeof(ans));
      if (siz[i] * 3 <= siz2[i] * 2)
        work1(i);
      else
        work2(i);
      memcpy(tmp, as, sizeof(tmp));
      memset(as, 0, sizeof(as));
      for (int a = 0; a <= k; a++)
        for (int b = 0; a + b <= k; b++)
          as[a + b] = (as[a + b] + 1ll * tmp[a] * ans[b]) % p;
    }
  int res = 0;
  for (int i = 0; i <= k; i++) res = (res + 1ll * as[i] * fac[n - i]) % p;
  printf("%d", res);
  return 0;
}
