#include <bits/stdc++.h>
using namespace std;
struct UnionFind {
  vector<int> par;
  UnionFind(int size) : par(size) { iota(begin(par), end(par), 0); }
  int root(int a) {
    if (a == par[a]) return a;
    return par[a] = root(par[a]);
  }
  void unite(int A, int B) { par[root(B)] = root(A); }
  bool eq(int a, int b) { return root(a) == root(b); }
};
const int MOD = 1000000007;
long long powmod(long long x, long long y) {
  long long res = 1;
  while (y--) (res *= x) %= MOD;
  return res;
}
vector<int> G[100010];
int col[100010];
bool seen[100010];
bool bipartite(int v, int c) {
  if (col[v] != -1) return col[v] == c;
  col[v] = c;
  bool res = true;
  for (const int &w : G[v]) {
    res &= bipartite(w, 1 - c);
  }
  return res;
}
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  vector<pair<int, int>> C0, C1;
  for (int i = 0; i < (int)(m); i++) {
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    a--;
    b--;
    if (c == 0) {
      C0.push_back({a, b});
    } else {
      C1.push_back({a, b});
    }
  }
  UnionFind uf(n);
  for (const auto &p : C1) {
    if (!uf.eq(p.first, p.second)) {
      uf.unite(p.first, p.second);
    }
  }
  for (const auto &p : C0) {
    if (uf.eq(p.first, p.second)) {
      puts("0");
      return 0;
    }
    int a = uf.root(p.first), b = uf.root(p.second);
    G[a].push_back(b);
    G[b].push_back(a);
  }
  for (int i = 0; i < (int)(n); i++) {
    if (!G[i].empty()) {
      sort((G[i]).begin(), (G[i]).end());
      (G[i]).erase(unique((G[i]).begin(), (G[i]).end()), (G[i]).end());
    }
  }
  int bp = 0, sp = 0;
  memset(col, -1, sizeof(col));
  for (int i = 0; i < n; i++) {
    int w = uf.root(i);
    if (col[w] != -1) continue;
    if (G[w].size() == 0) {
      col[w] = 114514;
      sp++;
    } else {
      if (bipartite(w, 0)) {
        bp++;
      } else {
        puts("0");
        return 0;
      }
    }
  }
  if (bp == 0) {
    cout << powmod(2, sp - 1) << endl;
  } else {
    cout << (powmod(2, bp - 1) * powmod(2, sp)) % MOD << endl;
  }
}
