#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = double;
const int mxn = 1e5 + 10;
const ll inf = 1e18;
const int mod = 1e9 + 7;
int n, m, pa[mxn];
int find(int u) {
  if (u == pa[u]) return pa[u];
  return pa[u] = find(pa[u]);
}
void unite(int a, int b) {
  a = find(a);
  b = find(b);
  if (a != b) pa[b] = a;
}
void init() {
  for (int i = 1; i <= n; i++) pa[i] = i;
}
struct Edge {
  int a, b, c;
  Edge() {}
  Edge(int _a, int _b, int _c) : a(_a), b(_b), c(_c) {}
};
set<int> adj[mxn];
bool ok = 1, color[mxn], vis[mxn];
void dfs(int v, bool c) {
  if (vis[v]) {
    if (c != color[v]) ok = 0;
    return;
  }
  color[v] = c;
  vis[v] = 1;
  for (int x : adj[v]) {
    if (vis[x] and color[x] == c) ok = 0;
    if (!vis[x]) dfs(x, !c);
  }
}
signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cin >> n >> m;
  vector<Edge> edges;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    edges.push_back(Edge(a, b, c));
  }
  init();
  for (auto edge : edges) {
    if (edge.c) {
      unite(edge.a, edge.b);
    }
  }
  for (auto edge : edges) {
    if (!edge.c) {
      adj[find(edge.a)].insert(find(edge.b));
      adj[find(edge.b)].insert(find(edge.a));
    }
  }
  for (int i = 1; i <= n; i++)
    if (!vis[find(i)]) dfs(find(i), 1);
  if (!ok) {
    cout << 0 << '\n';
    return 0;
  }
  init();
  for (auto edge : edges) {
    unite(edge.a, edge.b);
  }
  set<int> tmp;
  for (int i = 1; i <= n; i++) tmp.insert(find(i));
  int sz = tmp.size();
  sz--;
  ll cur = 1;
  for (int i = 0; i < sz; i++) cur = 2 * cur % mod;
  cout << cur << '\n';
  return 0;
}
