#include<bits/stdc++.h>
using namespace std;
int fn(int ii)
{
    int a=0;
    for(int i=0;i<20;i++)
    {
        if(((1 << i) & ii)!=0)
         a++;
    }
    return a;
}
int gn(map<int,int> mp,int i)
{
    vector<int> vc;
    for(int j=0;j<20;j++)
    {
        if(((1 << j) & i)!=0)
         vc.push_back(j+1);
    }
    for(auto ii : mp)
    {
        int k=0;
        for(int j=0;j<vc.size();j++)
        {
            if(vc[j]<=ii.first) k++;
        }
        if(k>ii.second)
        return 0;
    }
    return 1;
}
int main()
{
       ios_base::sync_with_stdio(false);
    cin.tie(NULL);
     int n,m;
     cin>>n>>m;
     map<int,int> a[n];
     for(int i=0;i<m;i++)
     {
         int x,y,z;
         cin>>x>>y>>z;
         x--;
         if(a[x].find(y)==a[x].end())
         a[x][y]=z;
         else a[x][y]=min(a[x][y],z);
     }
     int sz=(1 << n);
     long long int dp[sz];
     for(int i=0;i<sz;i++)
      dp[i]=0;
     dp[0]=1; 
     for(int i=1;i<sz;i++)
     {
         //to arrange bit'th no of elemnts 
         int k=fn(i);
         if(gn(a[k-1],i)==1)//has conditions
         {
             for(int j=0;j<n;j++)
             {
                 if(((1 << j) & i)!=0)
                 dp[i]+=dp[i-(1 << j)];
             }
         }
     }
     cout<<dp[sz-1];
    return 0;
}
#pragma region
#ifdef LOCAL
#include "pch.h"
#else
#include <bits/stdc++.h>
#endif

// debug
template<typename ... Types>
void __read(Types& ... args) {
  ((std::cin >> args), ...);
}
#define read(type, ...) type  __VA_ARGS__; __read(__VA_ARGS__)

template <typename Type, typename... Types>
auto print(Type const &arg, Types const &... args) {
  std::cout << arg, ((std::cout << " " << args), ...), std::cout << std::endl;
}
template <typename Type, typename... Types>
auto print_debug(Type const &arg, Types const &... args) {
  std::cout << arg, ((std::cout << " | " << args), ...), std::cout << std::endl;
}
#ifdef LOCAL
#define debug(...) do{std::cout <<  __LINE__ << ": [" << #__VA_ARGS__ << "]: ", print_debug(__VA_ARGS__);}while(0)
#else
#define debug(...) 1
#endif

#define __DEF_PRINTER(container)                                          \
template<typename T>                                                      \
std::ostream& operator<<(std::ostream& out, container<T> const& a)        \
{                                                                         \
  size_t len = a.size();                                                  \
  for(auto x : a) out << x << " \n"[len--==0];                            \
  return out;                                                             \
}

__DEF_PRINTER(std::vector)
__DEF_PRINTER(std::set)
__DEF_PRINTER(std::unordered_set)
// end debug

#define ALL(container) std::begin(container), std::end(container)
#define RANGE(container, lo, hi) std::begin(container)+(lo), std::begin(container)+(hi)

const char nl = '\n';
using std::cout;
using std::cin;

template <typename T>
void minmax(T k1, T k2, T& min, T& max) {
  min = std::min(k1, k2);
  max = std::max(k1, k2);
}

std::vector<int> iota(int size) {
  std::vector<int> res(size);
  std::iota(res.begin(), res.end(), 0);
  return res;
}

template <typename Iter>
auto counter(Iter from, Iter to) {
  std::map<typename Iter::value_type, int> res;
  while(from != to) res[*from++]++;
  return res;
}

const long long mod = 1e9+7;
long long reduce_mod(long long a) {
  return (a % mod + mod) % mod;
}
long long add(long long a, long long b) {
  return reduce_mod(a + b);
}
long long mult(long long a, long long b) {
  return reduce_mod(a * b);
}

std::string yn(bool yes) {
  return yes ? "yes" : "no";
}

#pragma endregion

int main() {
  cin.tie(0)->sync_with_stdio(false);

  read(int, n, m);

  std::vector<int> x(m), y(m), z(m);
  for(int i = 0; i < m; i++) {
    read(int, xi, yi, zi);
    x[i] = xi, y[i] = yi, z[i] = zi;
  }

  std::vector<long long> dp(1<<n);
  dp[0] = 1;
  for (int mask = 0; mask < 1<<n; mask++) {
    int c = __builtin_popcount(mask);
#if 1 // v2
    int rest = (((1<<n)-1) & ~mask);
    while(rest) {
      int mask2 = mask|(rest&-rest);
      rest-=rest&-rest;
      int valid = 1;
      for (int k = 0; k < m; k++) {
        if (x[k] == c+1 && __builtin_popcount(mask2 & ((1<<y[k])-1)) > z[k]) {
          valid = 0;
          break;
        }
      }
      if (valid) {
        dp[mask2] += dp[mask];
      }
    }
#else
    for (int j = 0; j < n; j++) {
      if (mask&(1<<j)) continue;
      int mask2 = mask|(1<<j);
      int valid = 1;
      for (int k = 0; k < m; k++) {
        if (x[k] == c+1 && __builtin_popcount(mask2 & ((1<<y[k])-1)) > z[k]) {
          valid = 0;
          break;
        }
      }
      if (valid) {
        dp[mask2] += dp[mask];
      }
    }
#endif
  }
  print(dp[(1<<n)-1]);
}