#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 10 ;
const int mod = 31011 ;
struct Edge {
int now, to, val;
} edge[ maxn] ;
struct Mintree {
int l, r, val;
} mintree[ maxn] ;
int fa[ maxn] ;
int n, m, sum;
int cmp ( Edge a, Edge b) {
return a. val < b. val;
}
int findfa ( int x) {
if ( x == fa[ x] ) return x;
return x = findfa ( fa[ x] ) ;
}
void dfs ( int x, int now, int k) {
if ( now == mintree[ x] . r + 1 ) {
if ( k == mintree[ x] . val) sum++ ;
return ;
}
int fax = findfa ( edge[ now] . now) , fay = findfa ( edge[ now] . to) ;
if ( fax != fay) {
fa[ fax] = fay;
dfs ( x, now + 1 , k + 1 ) ;
fa[ fax] = fax; fa[ fay] = fay;
}
dfs ( x, now + 1 , k) ;
}
int main ( ) {
cin >> n >> m;
for ( int i = 1 ; i <= n; i++ ) {
fa[ i] = i;
}
for ( int i = 1 ; i <= m; i++ ) {
cin >> edge[ i] . now >> edge[ i] . to >> edge[ i] . val;
}
sort ( edge + 1 , edge + m + 1 , cmp) ;
int cnt = 0 , cntt = 0 ;
for ( int i = 1 ; i <= m; i++ ) {
if ( edge[ i] . val != edge[ i - 1 ] . val) {
cnt++ ;
mintree[ cnt] . l = i;
mintree[ cnt - 1 ] . r = i - 1 ;
}
int fax = findfa ( edge[ i] . now) ;
int fay = findfa ( edge[ i] . to) ;
if ( fax != fay) {
fa[ fax] = fay;
mintree[ cnt] . val++ ;
cntt++ ;
}
}
mintree[ cnt] . r = m;
if ( cntt != n - 1 ) {
cout << 0 ;
return 0 ;
}
int ans = 1 ;
for ( int i = 1 ; i <= n; i++ ) fa[ i] = i;
for ( int i = 1 ; i <= cnt; i++ ) {
sum = 0 ;
dfs ( i, mintree[ i] . l, 0 ) ;
ans = ( ans * sum) % mod;
for ( int j = mintree[ i] . l; j <= mintree[ i] . r; j++ ) {
int fax = findfa ( edge[ j] . now) , fay = findfa ( edge[ j] . to) ;
if ( fax != fay) fa[ fax] = fay;
}
}
cout << ans;
return 0 ;
}