#include <bits/stdc++.h>   using namespace std;   void run(vector<vector<int>> &sets, int **sum);   pair<vector<vector<int>>, int **> precalc();   const int MAXB = 5;   const int MOD = 1e9 + 7;   int main() {     ios::sync_with_stdio(false);     cout.tie(0);     auto precalc_vals = precalc();     run(precalc_vals.first, precalc_vals.second);   }   template <typename type>   type *farray(int n) {     return (type *)malloc(n * sizeof(type));   }   template <typename type>   type *farray(int n, type val) {     auto res = farray<type>(n);     fill(res, res + n, val);     return res;   }   template <typename type>   type **dim2_farray(int n, int m) {     auto res = farray<type *>(n);     for (int i = 0; i < n; i++) {       res[i] = farray<type>(m);     }     return res;   }   template <typename type>   type **dim2_farray(int n, int m, type val) {     auto res = farray<type *>(n);     for (int i = 0; i < n; i++) {       res[i] = farray<type>(m, val);     }     return res;   }   template <typename type>   void dim2_free(type *arr, int n) {     for (int i = 0; i < n; i++) free(arr[i]);     free(arr);   }   bool gauss(bool **matrix, bool *vec, int n, int m) {     if (m > n) return false;     for (int k = 0; k < m; k++) {       int st = k;       for (; st < n && matrix[st][k] == 0; st++)         ;       if (st == n) return false;       for (int c = 0; c < m; c++) {         swap(matrix[st][c], matrix[k][c]);       }       swap(vec[st], vec[k]);       for (int r = st + 1; r < n; r++) {         if (matrix[r][k] == 0) continue;         for (int c = k; c < m; c++) {           matrix[r][c] -= matrix[k][c];         }         vec[r] -= vec[k];       }     }     for (int k = m - 1; k >= 0; k--) {       for (int r = k - 1; r >= 0; r--) {         if (matrix[r][k] == 0) continue;         matrix[r][k] -= 1;         vec[r] -= vec[k];       }     }     for (int k = m; k < n; k++) {       bool val = 0;       for (int c = 0; c < m; c++) {         val += matrix[k][c] * vec[c];       }       if (val != vec[k]) return false;     }     return true;   }   bool **to_matrix(const vector<int> &a) {     int len = (int)a.size();     auto matrix = dim2_farray<bool>(MAXB, len);     for (int i = 0; i < len; i++) {       for (int b = 0; b < MAXB; b++) {         matrix[b][i] = (a[i] & (1 << b)) > 0;       }     }     return matrix;   }   bool indep(const vector<int> &a) {     int len = (int)a.size();     auto matrix = to_matrix(a);     auto vec = farray<bool>(MAXB, 0);     return gauss(matrix, vec, MAXB, len);   }   bool *bin(int a) {     auto res = farray<bool>(MAXB);     for (int i = 0; i < MAXB; i++) {       res[i] = a & (1 << i);     }     return res;   }   bool the_same(const vector<int> &a, const vector<int> &b) {     if (a.size() != b.size()) return false;     int len = b.size();     for (int i = 0; i < len; i++) {       auto a_matrix = to_matrix(a);       if (!gauss(a_matrix, bin(b[i]), MAXB, len)) {         dim2_free(a_matrix, MAXB);         return false;       }       dim2_free(a_matrix, MAXB);     }     return true;   }   void precalc_sets(int from, vector<vector<int>> &ans, vector<int> &cur,                     int k = 0) {     cur.push_back(0);     for (int i = from; i < (1 << MAXB); i++) {       cur.back() = i;       if (indep(cur)) {         bool new_one = true;         for (auto &v : ans) {           if (the_same(cur, v)) {             new_one = false;             break;           }         }         if (new_one) {           ans.push_back(cur);           precalc_sets(i + 1, ans, cur, k + 1);         }       }     }     cur.pop_back();   }   int set_id(vector<int> &basis, vector<vector<int>> &sets) {     for (int i = 0; i < (int)sets.size(); i++) {       if (the_same(basis, sets[i])) {         return i;       }     }     return -1;   }   int **precalc_sums(vector<vector<int>> &sets) {     int n = (int)sets.size();     auto res = dim2_farray<int>(n, n);     for (int i = 0; i < n; i++) {       for (int j = 0; j < n; j++) {         vector<int> cur = sets[i];         cur.insert(cur.end(), sets[j].begin(), sets[j].end());         if (indep(cur)) {           res[i][j] = set_id(cur, sets);         } else {           res[i][j] = -1;         }       }     }     return res;   }   pair<vector<vector<int>>, int **> precalc() {     vector<vector<int>> sets(1);     vector<int> cur;     precalc_sets(0, sets, cur);     auto sums = precalc_sums(sets);     return {sets, sums};   }   struct Graph {     int *head, *nxt, *eto, *cost, eto_ptr = 0;     Graph(int n, int m) {       head = farray<int>(n, -1);       nxt = farray<int>(m);       eto = farray<int>(m);       cost = farray<int>(m);     }     void add_edge(int from, int to, int c) {       eto[eto_ptr++] = to;       nxt[eto_ptr - 1] = head[from];       head[from] = eto_ptr - 1;       cost[eto_ptr - 1] = c;     }   };   void get_basis(int v, Graph &graph, vector<bool> &used, int *path_xor,                  vector<int> &basis, int p = -1) {     used[v] = true;     for (int e = graph.head[v]; e != -1; e = graph.nxt[e]) {       int u = graph.eto[e];       if (u == p || u == 1) continue;       if (!used[u]) {         path_xor[u] = path_xor[v] ^ graph.cost[e];         get_basis(u, graph, used, path_xor, basis, v);       } else if (u < v) {         basis.push_back(path_xor[v] ^ path_xor[u] ^ graph.cost[e]);       }     }   }   void run(vector<vector<int>> &sets, int **sums) {     int n, m;     cin >> n >> m;     Graph graph(n + 1, m * 2);     for (int i = 0; i < m; i++) {       int u, v, c;       cin >> u >> v >> c;       graph.add_edge(u, v, c);       graph.add_edge(v, u, c);     }     auto near_one = farray<int>(n + 1, -1);     for (int e = graph.head[1]; e != -1; e = graph.nxt[e]) {       int u = graph.eto[e];       near_one[u] = graph.cost[e];     }     vector<bool> used(n + 1);     used[1] = true;     vector<vector<int>> dims = {{}};     auto path_xor = farray<int>(n + 1, 0);     for (int v = 2; v <= n; v++) {       if (used[v] || near_one[v] == -1) continue;       int u = -1, c = -1;       for (int e2 = graph.head[v]; e2 != -1; e2 = graph.nxt[e2]) {         u = graph.eto[e2];         c = graph.cost[e2];         if (near_one[u] != -1) {           break;         }         u = -1;       }       vector<int> basis;       get_basis(v, graph, used, path_xor, basis);       if (!indep(basis)) continue;       dims.push_back({set_id(basis, sets)});       if (u != -1) {         dims.back().push_back(dims.back().back());         basis.push_back(near_one[v] ^ near_one[u] ^ c);         if (indep(basis)) {           dims.back().push_back(set_id(basis, sets));         }       }     }     int p = sets.size();     int k = dims.size();     auto dp = dim2_farray<int>(k, p, 0);     dp[0][0] = 1;     for (int i = 1; i < k; i++) {       for (int d = 0; d < p; d++) {         dp[i][d] = dp[i - 1][d];       }       for (int d = 0; d < p; d++) {         for (int a : dims[i]) {           if (sums[d][a] == -1) continue;           int new_dim = sums[d][a];           dp[i][new_dim] = (dp[i][new_dim] + dp[i - 1][d]) % MOD;         }       }     }     int ans = 0;     for (int i = 0; i < p; i++) {       ans = (ans + dp[k - 1][i]) % MOD;     }     cout << ans << endl;   }