#include <bits/stdc++.h>
using namespace std;
using ll = long long int;
using ld = long double;
using vi = vector<int>;
using vl = vector<ll>;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pll = pair<ll, ll>;
using vs = vector<string>;
using vpi = vector<pii>;
struct dsu {
  vi t;
  dsu(int N) {
    t.resize(N);
    iota(t.begin(), t.end(), 0);
  }
  int get(int a) {
    if (t[a] == a) return a;
    return t[a] = get(t[a]);
  }
  void merge(int a, int b) {
    a = get(a);
    b = get(b);
    if (a != b) {
      t[b] = a;
    }
  }
};
void dfs(int u, vector<vi> &g, vi &used, int need = 1) {
  if (used[u] != 0 && used[u] != need) {
    cout << 0;
    exit(0);
  } else if (used[u] != 0)
    return;
  used[u] = need;
  need = (need + 1 - 1) % 2 + 1;
  for (int v : g[u]) {
    dfs(v, g, used, need);
  }
}
void solve() {
  int n, m;
  cin >> n >> m;
  dsu k(n);
  vpi oth;
  for (int i = 0; i < m; ++i) {
    int u, v, x;
    cin >> u >> v >> x;
    --u, --v;
    if (x == 1) {
      k.merge(u, v);
    } else {
      oth.push_back(make_pair(u, v));
    }
  }
  vi comp(n, -1);
  int nxt = 0;
  for (int i = 0; i < n; ++i) {
    int r = k.get(i);
    if (comp[r] == -1) comp[r] = nxt++;
    comp[i] = comp[r];
  }
  vector<vi> g(nxt);
  dsu x(nxt);
  for (auto i : oth) {
    int fi = comp[i.first];
    int se = comp[i.second];
    g[fi].push_back(se);
    g[se].push_back(fi);
    x.merge(fi, se);
  }
  vi used(nxt);
  for (int i = 0; i < nxt; ++i) {
    if (!used[i]) {
      dfs(i, g, used);
    }
  }
  set<int> a;
  for (int i = 0; i < nxt; ++i) a.insert(x.get(i));
  ll ans = 1;
  for (int i = 0; i < ((int)(a).size()) - 1; ++i) {
    ans *= 2;
    ans %= (ll)(1e9 + 7);
  }
  cout << ans;
}
int main() {
  ios::sync_with_stdio(false);
  solve();
  return 0;
}
