#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define all(a) a.begin(),a.end()
typedef pair<ll,ll> pi;

//__builtin_popcountll(2) (the number of ones in the binary representation)
//__builtin_clz(2) (number of leading zeroes)
//__builtin_ctz(2) (number of trailing zeroes)

/*#include <ext/pb_ds/assoc_container.hpp> 
#include <ext/pb_ds/tree_policy.hpp> 
using namespace __gnu_pbds; 
  
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>*/
// s.find_by_order(k)(returns iterator to kth element), s.order_of_key(k)(number of elements less than number)

ll mod = 1e9+7;
vector<ll> fact(1);
/*vector<ll> spf(10000005), cntPrime(10000005);

void spff(){
    int i;
    for(i=1;i<10000005;i++) spf[i] = i;
    for(i=2;i*i<10000005;i++)
    {
        if(spf[i] != i) continue;
        for(int j = i*i; j < 10000005; j+= i){
            if(spf[j]==j) spf[j] = i;
        }
    }
    for(i=1;i<10000005;i++){
        if(spf[i] != spf[i/spf[i]]){
            cntPrime[i] = cntPrime[i/spf[i]]+1;
        }
        else cntPrime[i] = cntPrime[i/spf[i]];
    }
}
while(spf[a[i]]!=a[i]){
              z=spf[a[i]];
              while(a[i]%z==0) a[i]/=z;
              m[z]++;
          }
          if(a[i]>1) m[a[i]]++;*/
 
ll gcd(ll a, ll b) 
{ 
    if (b == 0) 
        return a; 
    return gcd(b, a % b);       
}
 
ll power(ll x, ll y) 
{ 
    ll temp; 
    if( y == 0) 
        return 1; 
    temp = power(x, y/2); 
    if (y%2 == 0) 
        return temp*temp; 
    else
        return x*temp*temp; 
}
 
ll power(ll x, ll y, ll p) 
{ 
    ll res = 1; 
    x = x % p; 
  
    while (y > 0) { 
        if (y & 1) res = (res * x) % p; 
        y = y >> 1;
        x = (x * x) % p; 
    } 
    return res; 
} 
  
ll modInv(ll n, ll p) 
{ 
    return power(n, p - 2, p); 
} 
 
ll ncr(ll n, ll r) {return (n>=r?(fact[n]*modInv(fact[r],mod))%mod*modInv(fact[n-r],mod)%mod:0);}

ll add(ll a, ll b) {ll z=a+b; if(z>=mod) z -= mod; return z;}
ll sub(ll a, ll b) { return (a-b+mod)%mod;}
// LLONG_MAX

vector<pi> v[105];
vector<ll> dp((1<<18), -1);
ll n;

ll solve(ll mask){
    ll z=0, cnt = __builtin_popcountll(mask);
    if(cnt==0) return 1;
    if(dp[mask] != -1) return dp[mask];

    for(auto i: v[cnt]){
        ll pre = mask%(1<<i.fi);
        pre = __builtin_popcountll(pre);
        if(pre > i.se) return 0;
    }
    for(ll i=0;i<n;i++){
        if(mask&(1<<i)){
            z += solve(mask^(1<<i));
        }
    }
    return dp[mask] = z;
}

int main()
{  
  ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
  ll t=1,i,j,m,x,y,z;
  //cin>>t;
  //fact[0]=1;
  //for(i=1;i<300003;i++)fact[i]=(fact[i-1]*i)%mod;
  while(t--)
  {
      cin>>n>>m;
      for(i=0;i<m;i++){
          cin>>x>>y>>z;
          v[x].pb(mp(y,z));
      }
      cout<<solve((1<<n)-1);
  }
}

#include<bits/stdc++.h>
using namespace std;
const int N=20;
int n,m,s[N],g[N][N];
long long dp[N][1<<N];
int main()
{
	cin>>n>>m;
	memset(g,0x3f,sizeof g);
	//前x个 最多有z个小于等于y    
	//y-1 映射到二进制的0 ~ n-1 
	for(int i=1,x,y,z; i<=m; ++i)
		cin>>x>>y>>z,--y,g[x][y]=min(g[x][y],z);
	dp[0][0]=1;
	
	for(int i=0; i<n; ++i)
		for(int s=0; s<1<<n; ++s)
		{
			long long v=dp[i][s];
			if(!v)
				continue;
			for(int j=0; j<n; ++j)
				if(!(s>>j&1))//如果第j个数没用过 
				{
					int t=s|1<<j;//用过之后的状态 
					bool ok=1;
					for(int k=0,s=0; k<n; ++k)
					{
						if((t>>k&1))
							++s;
						// 
						if(s>g[i+1][k])
							ok=0;
					}
					if(ok)
						dp[i+1][t]+=v;
				}
		}
	printf("%lld\n",dp[n][(1<<n)-1]);
	return 0;
}