#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;
}