#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>

using namespace std;

vector<int> cg[100005],pg[100005];
int marka[100005],m,n,otac[100005];
long long int res=1,mod=1000000007;

int nadji(int x)
{
    if(otac[x]==x) return x;
    else return nadji(otac[x]);
}
void spoj(int a,int b)
{
    int x,y;
    x=nadji(a); otac[a]=x;
    y=nadji(b); otac[b]=y;

    if(rand()%2) otac[x]=y;
    else otac[y]=x;
}

void dfs2(int cvor)
{
    int i,j,x;  marka[cvor]=1;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
    for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
}

void dfs(int cvor)
{
    int i,j,x;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0) {marka[x]=(-1) * marka[cvor]; dfs(x);}
    }

}

void ddffss(int cvor)
{
    int i,j,x; marka[cvor]=1;
     for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  {spoj(cvor,x); ddffss(x);}
    }
}

int jelidobro()
{
    int a,b,i,j;

    for(i=1;i<=n;i++)
    {
        for(j=0;j<pg[i].size();j++)
        {
           a=i; b=pg[i][j];
           if(nadji(a)!=nadji(b) && marka[a]==marka[b]) return 0;
           if(nadji(a)==nadji(b) && marka[a]!=marka[b]) return 0;
        }
    }
    return 1;
}

int main()
{
    int i,j,a,b,c,x,plave=0,ukomp=0;

    cin>>n>>m;
    for(i=1;i<=m;i++)
    {
        cin>>a>>b>>c;
        if(c==1)
        {
            cg[a].push_back(b);  cg[b].push_back(a);
        }
        else
        {
            plave++;
            pg[a].push_back(b);   pg[b].push_back(a);
        }
    }

    for(i=1;i<=n;i++) otac[i]=i;

    for(i=1;i<=n;i++)
    {
        if(marka[i]==0) {ddffss(i);}
    }

    for(i=0;i<=n;i++) marka[i]=0;
     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {marka[i]=1; dfs(i);}
     }

     x=jelidobro();

     if(x==0) res=0ll;
     else res=1ll;

     for(i=0;i<=n;i++) marka[i]=0;

     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {ukomp++; dfs2(i);}
     }

     for(i=1;i<ukomp;i++)  res=(res*2)%mod;

     cout<<res;

    return 0;
}


#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>

using namespace std;

vector<int> cg[100005],pg[100005];
int marka[100005],m,n,otac[100005];
long long int res=1,mod=1000000007;

int nadji(int x)
{
    if(otac[x]==x) return x;
    else return nadji(otac[x]);
}
void spoj(int a,int b)
{
    int x,y;
    x=nadji(a); otac[a]=x;
    y=nadji(b); otac[b]=y;

    otac[x]=y;
}

void dfs2(int cvor)
{
    int i,j,x;  marka[cvor]=1;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
    for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  dfs2(x);
    }
}

void dfs(int cvor)
{
    int i,j,x;
    for(i=0;i<pg[cvor].size();i++)
    {
        x=pg[cvor][i];
        if(marka[x]==0) {marka[x]=(-1) * marka[cvor]; dfs(x);}
    }

}

void ddffss(int cvor)
{
    int i,j,x; marka[cvor]=1;
     for(i=0;i<cg[cvor].size();i++)
    {
        x=cg[cvor][i];
        if(marka[x]==0)  {spoj(cvor,x); ddffss(x);}
    }
}

int jelidobro()
{
    int a,b,i,j;

    for(i=1;i<=n;i++)
    {
        for(j=0;j<pg[i].size();j++)
        {
           a=i; b=pg[i][j];
           if(nadji(a)!=nadji(b) && marka[a]==marka[b]) return 0;
           if(nadji(a)==nadji(b) && marka[a]!=marka[b]) return 0;
        }
    }
    return 1;
}

int main()
{
    int i,j,a,b,c,x,plave=0,ukomp=0;

    cin>>n>>m;
    for(i=1;i<=m;i++)
    {
        cin>>a>>b>>c;
        if(c==1)
        {
            cg[a].push_back(b);  cg[b].push_back(a);
        }
        else
        {
            plave++;
            pg[a].push_back(b);   pg[b].push_back(a);
        }
    }

    for(i=1;i<=n;i++) otac[i]=i;

    for(i=1;i<=n;i++)
    {
        if(marka[i]==0) {ddffss(i);}
    }

    for(i=0;i<=n;i++) marka[i]=0;
     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {marka[i]=1; dfs(i);}
     }

     x=jelidobro();

     if(x==0) res=0ll;
     else res=1ll;

     for(i=0;i<=n;i++) marka[i]=0;

     for(i=1;i<=n;i++)
     {
         if(marka[i]==0) {ukomp++; dfs2(i);}
     }

     for(i=1;i<ukomp;i++)  res=(res*2)%mod;

     cout<<res;

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+7, mod = 1000*1000*1000+7;
vector<int> adj[N];
vector<pair<int, int>> e;
int color[N], mark[N], par[N];
int root(int v)
{
	return (v == par[v] ? v : par[v] = root(par[v]));
}
void merge(int u, int v)
{
	v = root(v); u = root(u);
	par[u] = v;
}
void dfs(int v, int c = 1)
{
	color[v] = c;
	for (auto u : adj[v])
		if (color[u] == 0)
			dfs(u, c^2);
}

int main ()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int n, m; cin >> n >> m;
	for (int i = 0; i < n; i++) par[i] = i;
	for (int i = 0; i < m; i++)
	{
		int u, v, c; cin >> u >> v >> c;
		u--; v--;
		if (c == 1) merge(u, v);
		else e.push_back({u, v});
	}
	for (int i = 0; i < n; i++)
		if (par[i] == i)
			mark[i] = 1;
	for (auto p : e)
	{
		int u = p.first, v = p.second;
		u = root(u); v = root(v);
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	int ans = 0;
	for (int i = 0; i < n; i++)
	{
		if (mark[i] == 1 && color[i] == 0)
		{
			dfs(i);
			if (ans) ans = ans * 2 % mod;
			else ans = 1;
		}
	}
	for (auto p : e)
	{
		int u = p.first, v = p.second;
		u = root(u); v = root(v);
		if (color[u] == color[v])
			ans = 0;
	}

	cout << ans << endl;
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+7, mod = 1000*1000*1000+7;
vector<int> adj[N];
vector<pair<int, int>> e;
int color[N], mark[N], par[N];
int root(int v)
{
	return (v == par[v] ? v : par[v] = root(par[v]));
}
void merge(int u, int v)
{
	v = root(v); u = root(u);
	par[u] = v;
}
void dfs(int v, int c = 1)
{
	color[v] = c;
	for (auto u : adj[v])
		if (color[u] == 0)
			dfs(u, c^2);
}

int main ()
{
	int n, m; cin >> n >> m;
	for (int i = 0; i < n; i++) par[i] = i;
	for (int i = 0; i < m; i++)
	{
		int u, v, c; cin >> u >> v >> c;
		u--; v--;
		if (c == 1) merge(u, v);
		else e.push_back({u, v});
	}
	for (int i = 0; i < n; i++)
		if (par[i] == i)
			mark[i] = 1;
	for (auto p : e)
	{
		int u = p.first, v = p.second;
		u = root(u); v = root(v);
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	int ans = 0;
	for (int i = 0; i < n; i++)
	{
		if (mark[i] == 1 && color[i] == 0)
		{
			dfs(i);
			if (ans) ans = ans * 2 % mod;
			else ans = 1;
		}
	}
	for (auto p : e)
	{
		int u = p.first, v = p.second;
		u = root(u); v = root(v);
		if (color[u] == color[v])
			ans = 0;
	}

	cout << ans << endl;
	return 0;
}


#include <bits/stdc++.h>

#ifdef _WIN32
#define getchar_unlocked getchar
#endif
#define II (read32())
#define IU (readu32())
#define IL (read64())
#define IUL (readu64())
uint32_t readu32() { int c; while((c = getchar_unlocked()) < '0'); uint32_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return n; } uint64_t readu64() { int c; while((c = getchar_unlocked()) < '0'); uint64_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return n; } int32_t read32() { int c; while((c = getchar_unlocked()) < '-'); bool neg = c == '-'; if(neg) c = getchar_unlocked(); uint32_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return neg ? -(int32_t)n : n; } int64_t read64() { int c; while((c = getchar_unlocked()) < '-'); bool neg = c == '-'; if(neg) c = getchar_unlocked(); uint64_t n = c & 15; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return neg ? -(int64_t)n : n; }
template<typename T> void insf(std::vector<T> &c, T&& e) { c.push_back(std::move(e)); } template<typename T> void insf(std::vector<T> &c, const T& e) { c.push_back(e); } template<typename T, typename... A> void empf(std::vector<T> &c, A...a) { c.emplace_back(a...); } template<typename T> void insf(std::forward_list<T> &c, T&& e) { c.push_front(std::move(e)); } template<typename T> void insf(std::forward_list<T> &c, const T& e) { c.push_front(e); } template<typename T, typename... A> void empf(std::forward_list<T> &c, A...a) { c.emplace_front(a...); }template<typename Etags> struct h_edge { int v; operator int() { return v; } Etags tags; h_edge(int a, Etags b):v(a),tags(b) { } }; template<> struct h_edge<void> { int v; operator int() { return v; } }; template<typename Etags = void, template<class...>class CONT = std::forward_list> struct G_ { typedef h_edge<Etags> h_edge_t; CONT<h_edge_t>* aj = 0; int sz; void init(int n) { assert(n >= 0); delete[] aj; aj = new CONT<h_edge_t>[sz = n]; } G_() { } G_(int n) { init(n); } ~G_() { delete[] aj; } size_t size() { return sz; } CONT<h_edge_t>& adj(int v) { assert(v >= 0 && v < sz); return aj[v]; } void add(int u, int v) { insf(adj(u), v); insf(adj(v), u); } template<typename... T> void add(int u, int v, T... t) { empf(adj(u), v, Etags{t...}); empf(adj(v), u, Etags{t...}); } template<typename F> void readEdges(int off, int n, F f) { while(n--) { add(f()-off, f()-off); } } };
template<typename T, typename X> T bpow(T b, X x) { T r = 1, p = b; while(x) { if(x & 1) r = r * p; if(x >>= 1) p = p * p; } return r; }
template<typename T> struct xgcd_s { T m, n, gcd; }; template<typename T> xgcd_s<T> xgcd(T a, T b) { T m[] = {1,0}, n[] = {0,1}, q[] = {0,0}; for(int i = 0; ; i^=1) { m[i] -= m[i^1] * q[i]; n[i] -= n[i^1] * q[i]; if(!b) return xgcd_s<T>{m[i],n[i],a}; q[i] = a/b; a %= b; std::swap(a,b); } } template<unsigned M()> struct _intmod { private: struct _p {unsigned x; }; _intmod(_p x) { n = x.x; } public: unsigned n; _intmod() {n = 0;} _intmod(int x) { n = x<0? M()+x%(int)M(): x%M(); } _intmod(unsigned x) {n = x%M(); } _intmod(long long x) {n = unsigned(x<0? M()+x%(long long)M(): x%M()); } _intmod operator+(_intmod b) {return {n+b.n}; } _intmod operator*(_intmod b) {return {_p{unsigned((unsigned long long)n * b.n % M())}}; } _intmod operator-(_intmod b) {return {_p{n>=b.n? n-b.n : M()+n-b.n }}; } _intmod operator-() {return {_p{n?M()-n:0U}}; } _intmod& operator+=(_intmod b) { return(*this = *this + b); } _intmod& operator-=(_intmod b) { return(*this = *this - b); } _intmod& operator/=(_intmod b) { return(*this = *this / b); } _intmod& operator*=(_intmod b) { return(*this = *this * b); } static _intmod mulinv(_intmod n) { xgcd_s<signed> x = xgcd<signed>(n.n, M()); assert(x.gcd == 1); return x.m; } _intmod operator/(_intmod b) { return *this * mulinv(b); } bool operator==(_intmod b) { return n == b.n; } bool operator!=(_intmod b) { return n != b.n; } explicit operator int() { return n; } }; template<unsigned M()> std::ostream& operator<<(std::ostream& o, _intmod<M> n) { return o<<n.n; } template<unsigned M()> std::istream& operator>>(std::istream& i, _intmod<M>& n) { long long x; i>>x; n = x; return i; } template<unsigned M> unsigned intmod_unsignedconst() { static_assert(M>0 && M<(1U<<31), "modulus bad"); return M; } template<unsigned*M> unsigned intmod_unsignedptr() { return *M; } template<unsigned M> using intmod = _intmod<intmod_unsignedconst<M> >; template<unsigned*M> using intmodv = _intmod<intmod_unsignedptr<M> >; static_assert(std::is_trivially_copyable<intmod<3> >::value, "");
struct unionf { int *ut = nullptr; void init(size_t n) { delete[] ut; ut = new int[n]; memset(ut, -1, n*sizeof(*ut)); } unionf() {} unionf(size_t n) { init(n); } ~unionf() { delete[] ut; } int rtnc(int x) { while(ut[x] >= 0) x = ut[x]; return x; } void compress(int x, int r) { if(x == r) return; for(;;) { int t = ut[x]; if(t == r) break; ut[x] = r; x = t; } } int rt(int x) { int r = rtnc(x); compress(x, r); return r; } int un(int x, int y) { int rx = rtnc(x), ry = rtnc(y); if(rx == ry) return rx; int sx = -ut[rx], sy = -ut[ry]; if (sx > sy) std::swap(x, y), std::swap(sx, sy), std::swap(rx, ry); ut[rx] = ry; compress(y, ry); compress(x, ry); ut[ry] -= sx; return ry; } };

using namespace std;

#define N 100000
int zc[N];

struct e {int u, v, w; };

void dfs(G_<int>& g, int v, int p, int k) {
    zc[v] = k;
    for(auto x: g.adj(v)) {
        if(x.v != p)
            dfs(g, x.v, v, k + (1^x.tags)) ;
    }
}
int main() {
    int n=IU, m=IU;
    G_<int> g(n);
    unionf uf(n);
    vector<e> ebad;
    for(int mm = m; mm--; ) {
        int u=IU-1, v=IU-1, w=IU;
        int ru = uf.rt(u), rv = uf.rt(v);
        if(ru == rv) {
            ebad.push_back({u,v,w});
        } else {
            uf.un(ru, rv);
            g.add(u, v, w);
        }
    }

    for(int i = 0; i < n; i++)
        if(uf.ut[i] < 0)
            dfs(g, i, -1, 0);

    for(auto x: ebad) {
        if( (zc[x.u]+zc[x.v] & 1) != (x.w^1) ) {
            cout<<0;
            return 0;
        }
    }

    cout<<bpow<intmod<1000000007>, int>(2, n-1 - m + ebad.size());

    return 0;
}


#include <bits/stdc++.h>

#ifdef _WIN32
#define getchar_unlocked getchar
#endif
#define II (read32())
#define IU (readu32())
#define IL (read64())
#define IUL (readu64())
uint32_t readu32() { int c; while((c = getchar_unlocked()) < '0'); uint32_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return n; } uint64_t readu64() { int c; while((c = getchar_unlocked()) < '0'); uint64_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return n; } int32_t read32() { int c; while((c = getchar_unlocked()) < '-'); bool neg = c == '-'; if(neg) c = getchar_unlocked(); uint32_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return neg ? -(int32_t)n : n; } int64_t read64() { int c; while((c = getchar_unlocked()) < '-'); bool neg = c == '-'; if(neg) c = getchar_unlocked(); uint64_t n = c & 15; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return neg ? -(int64_t)n : n; }
template<typename T> void insf(std::vector<T> &c, T&& e) { c.push_back(std::move(e)); } template<typename T> void insf(std::vector<T> &c, const T& e) { c.push_back(e); } template<typename T, typename... A> void empf(std::vector<T> &c, A...a) { c.emplace_back(a...); } template<typename T> void insf(std::forward_list<T> &c, T&& e) { c.push_front(std::move(e)); } template<typename T> void insf(std::forward_list<T> &c, const T& e) { c.push_front(e); } template<typename T, typename... A> void empf(std::forward_list<T> &c, A...a) { c.emplace_front(a...); }template<typename Etags> struct h_edge { int v; operator int() { return v; } Etags tags; h_edge(int a, Etags b):v(a),tags(b) { } }; template<> struct h_edge<void> { int v; operator int() { return v; } }; template<typename Etags = void, template<class...>class CONT = std::forward_list> struct G_ { typedef h_edge<Etags> h_edge_t; CONT<h_edge_t>* aj = 0; int sz; void init(int n) { assert(n >= 0); delete[] aj; aj = new CONT<h_edge_t>[sz = n]; } G_() { } G_(int n) { init(n); } ~G_() { delete[] aj; } size_t size() { return sz; } CONT<h_edge_t>& adj(int v) { assert(v >= 0 && v < sz); return aj[v]; } void add(int u, int v) { insf(adj(u), v); insf(adj(v), u); } template<typename... T> void add(int u, int v, T... t) { empf(adj(u), v, Etags{t...}); empf(adj(v), u, Etags{t...}); } template<typename F> void readEdges(int off, int n, F f) { while(n--) { add(f()-off, f()-off); } } };
template<typename T, typename X> T bpow(T b, X x) { T r = 1, p = b; while(x) { if(x & 1) r = r * p; if(x >>= 1) p = p * p; } return r; }
template<typename T> struct xgcd_s { T m, n, gcd; }; template<typename T> xgcd_s<T> xgcd(T a, T b) { T m[] = {1,0}, n[] = {0,1}, q[] = {0,0}; for(int i = 0; ; i^=1) { m[i] -= m[i^1] * q[i]; n[i] -= n[i^1] * q[i]; if(!b) return xgcd_s<T>{m[i],n[i],a}; q[i] = a/b; a %= b; std::swap(a,b); } } template<unsigned M()> struct _intmod { private: struct _p {unsigned x; }; _intmod(_p x) { n = x.x; } public: unsigned n; _intmod() {n = 0;} _intmod(int x) { n = x<0? M()+x%(int)M(): x%M(); } _intmod(unsigned x) {n = x%M(); } _intmod(long long x) {n = unsigned(x<0? M()+x%(long long)M(): x%M()); } _intmod operator+(_intmod b) {return {n+b.n}; } _intmod operator*(_intmod b) {return {_p{unsigned((unsigned long long)n * b.n % M())}}; } _intmod operator-(_intmod b) {return {_p{n>=b.n? n-b.n : M()+n-b.n }}; } _intmod operator-() {return {_p{n?M()-n:0U}}; } _intmod& operator+=(_intmod b) { return(*this = *this + b); } _intmod& operator-=(_intmod b) { return(*this = *this - b); } _intmod& operator/=(_intmod b) { return(*this = *this / b); } _intmod& operator*=(_intmod b) { return(*this = *this * b); } static _intmod mulinv(_intmod n) { xgcd_s<signed> x = xgcd<signed>(n.n, M()); assert(x.gcd == 1); return x.m; } _intmod operator/(_intmod b) { return *this * mulinv(b); } bool operator==(_intmod b) { return n == b.n; } bool operator!=(_intmod b) { return n != b.n; } explicit operator int() { return n; } }; template<unsigned M()> std::ostream& operator<<(std::ostream& o, _intmod<M> n) { return o<<n.n; } template<unsigned M()> std::istream& operator>>(std::istream& i, _intmod<M>& n) { long long x; i>>x; n = x; return i; } template<unsigned M> unsigned intmod_unsignedconst() { static_assert(M>0 && M<(1U<<31), "modulus bad"); return M; } template<unsigned*M> unsigned intmod_unsignedptr() { return *M; } template<unsigned M> using intmod = _intmod<intmod_unsignedconst<M> >; template<unsigned*M> using intmodv = _intmod<intmod_unsignedptr<M> >; static_assert(std::is_trivially_copyable<intmod<3> >::value, "");
struct unionf { int *ut = nullptr; void init(size_t n) { delete[] ut; ut = new int[n]; memset(ut, -1, n*sizeof(ut)); } unionf() {} unionf(size_t n) { init(n); } ~unionf() { delete[] ut; } int rtnc(int x) { while(ut[x] >= 0) x = ut[x]; return x; } void compress(int x, int r) { if(x == r) return; for(;;) { int t = ut[x]; if(t == r) break; ut[x] = r; x = t; } } int rt(int x) { int r = rtnc(x); compress(x, r); return r; } int un(int x, int y) { int rx = rtnc(x), ry = rtnc(y); if(rx == ry) return rx; int sx = -ut[rx], sy = -ut[ry]; if (sx > sy) std::swap(x, y), std::swap(sx, sy), std::swap(rx, ry); ut[rx] = ry; compress(y, ry); compress(x, ry); ut[ry] -= sx; return ry; } };

using namespace std;

#define N 100000
int c[N];

struct e {int u, v, w; };

void dfs(G_<int>& g, int v, int p, int k) {
    c[v] = k;
    for(auto x: g.adj(v)) {
        if(x.v != p)
            dfs(g, x.v, v, k + x.tags);
    }
}
int main() {
    int n=IU, m=IU;
    G_<int> g(n);
    unionf uf(n);
    vector<e> ebad;
    for(int mm = m; mm--; ) {
        int u=IU-1, v=IU-1, w=IU;
        int ru = uf.rt(u), rv = uf.rt(v);
        if(ru == rv) {
            ebad.push_back({u,v,w});
        } else {
            uf.un(ru, rv);
            g.add(u, v, w);
        }
    }

    for(int i = 0; i < n; i++)
        if(!~uf.ut[i])
            dfs(g, i, -1, 0);

    for(auto x: ebad) {
        if( (c[x.u]+c[x.v] & 1) != x.w) {
            cout<<0;
            return 0;
        }
    }

    cout<<bpow<intmod<1000000007>, int>(2, n-1 - m + ebad.size());

    return 0;
}


/*Copyright Alexey 2015*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>

typedef long long ll;

using namespace std;

int n, m, mod = 1000 * 1000 * 1000 + 7, cn = 0;
class Edge{
 public:
  int to;
  bool col;
  Edge() {
  }
  Edge(int to, bool col) {
    this->to = to;
    this->col = col;
  }
};
vector < int > number, used, even;
vector < vector < Edge > > graph;
vector < vector < int > > gr;

void dfs1(int v, int nu) {
  used[v] = true;
  number[v] = nu;
  for (int i = 0; i < graph[v].size(); ++i) {
    Edge e = graph[v][i];
    if (!used[e.to] && e.col) {
      dfs1(e.to, nu);
    }
  }
}
void dfs2(int v) {
  used[v] = true;
  for (int i = 0; i < graph[v].size(); ++i) {
    Edge e = graph[v][i];
    if (!used[e.to] && e.col) {
      dfs2(e.to);
    }
    if (!e.col) {
      gr[number[v]].push_back(number[e.to]);
    }
  }
}
bool dfs3(int v, int s) {
  used[v] = true;
  even[v] = s;
  for (int x : gr[v]) {
    if (!used[x]) {
      if (!dfs3(x, s ^ 1)) {
        return false;
      }
    } else if (even[v] == even[x]) {
      return false;
    }
  }
  return true;
}
void solve() {
  scanf("%d%d", &n, &m);
  int a, b, c;
  graph.resize(n);
  for (int i = 0; i < m; ++i) {
    scanf("%d%d%d", &a, &b, &c);
    --a; --b;
    graph[a].push_back(Edge(b, c == 1));
    graph[b].push_back(Edge(a, c == 1));
  }
  used.resize(n, 0);
  number.resize(n, 0);
  for (int i = 0; i < n; ++i) {
    if (used[i] == 0) {
      dfs1(i, cn++);
    }
  }
  even.resize(cn);
  gr.resize(cn);
  used.assign(n, 0);
  for (int i = 0; i < n; ++i) {
    if (used[i] == 0) {
      dfs2(i);
    }
  }
  used.assign(cn, 0);
  int all = 0;
  for (int i = 0; i < cn; ++i) {
    if (!used[i]) {
      all++;
      if (!dfs3(i, 0)) {
        cout << 0;
        return;
      }
    }
  }
  ll res = 1;
  for (int i = 0; i < all - 1; ++i) {
    res = (res * 2LL) % mod;
  }
  cout << res;
}
int main() {
  solve();
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define N (101*1000)
#define ll int
#define INF ((ll)1e9)
#define MOD ((ll)1e9+7)

ll n,m,par[N],mark[N],v,u,p,num_ed;
long long ans;
vector <ll> e[N];
pair<ll,ll> ed[N];

ll root(ll x){if(par[x]<0)return x;return par[x]=root(par[x]);}
void merge(ll x,ll y){if(root(x)==root(y))return ;par[root(y)]=root(x);}

void dfs(ll x)
{
    for(int i=0;i<e[x].size();i++)
    {
        if(mark[e[x][i]]==mark[x]){cout<<0;exit(0);}
        if(!mark[e[x][i]])mark[e[x][i]]=((mark[x]==1)?2:1),dfs(e[x][i]);
    }
}

int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for(int i=0;i<N;i++)par[i]=-i;
    for(int i=0;i<m;i++)
    {
        cin>>v>>u>>p;
        if(p)merge(v,u);
        else ed[num_ed++]={v,u};
    }
    for(int i=0;i<num_ed;i++)
    {
        if(root(ed[i].first)==root(ed[i].second))return cout<<0,0;
        v=-par[root(ed[i].first)],u=-par[root(ed[i].second)];
        e[v].push_back(u),e[u].push_back(v);
    }
    for(int i=1;i<=n;i++)
        if(!mark[i] && i==-par[root(i)])
        {
            if(!ans)ans=1;
            else ans*=2;ans%=MOD;
            mark[i]=1;
            dfs(i);
        }
    cout<<ans;
    return 0;
}


#include <cstdio>
#include <numeric>
#include <iostream>
#include <vector>
#include <set>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <bitset>
#include <queue>
#include <sstream>
#include <deque>

using namespace std;

#define mp make_pair
#define pb push_back
#define rep(i,n) for(int i = 0; i < (n); i++)
#define re return
#define fi first
#define se second
#define sz(x) ((int) (x).size())
#define all(x) (x).begin(), (x).end()
#define sqr(x) ((x) * (x))
#define sqrt(x) sqrt(abs(x))
#define y0 y3487465
#define y1 y8687969
#define fill(x,y) memset(x,y,sizeof(x))
#define prev PREV

typedef vector<int> vi;
typedef long long ll;
typedef long double ld;
typedef double D;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef vector<vi> vvi;

template<class T> T abs(T x) { re x > 0 ? x : -x; }

const int mod = 1000*1000*1000+7;

int n;
int m;
vi v[100000];
int p[100000];
int was[100000];
int col[100000];
int ea[100000];
int eb[100000];
int ec[100000];
vi w;

int gp (int x) {
    if (p[x] != x) p[x] = gp (p[x]);
    re p[x];
}

int go (int x, int c) {
    if (was[x]) re int (col[x] != c);
    col[x] = c;
    was[x] = 1;
    for (int i = 0; i < sz (v[x]); i++)
        if (go (v[x][i], 1 - c))
            re 1;
    re 0;
}

int main () {
    scanf ("%d%d", &n, &m);
    for (int i = 0; i < n; i++) p[i] = i;
    for (int i = 0; i < m; i++) {
        scanf ("%d%d%d", &ea[i], &eb[i], &ec[i]); ea[i]--; eb[i]--;
        if (ec[i]) {
            int a = gp (ea[i]);
            int b = gp (eb[i]);
            p[a] = b;
        }
    }
    for (int i = 0; i < m; i++)
        if (!ec[i]) {
            int a = gp (ea[i]);
            int b = gp (eb[i]);
            v[a].pb (b);
            v[b].pb (a);
        }
    for (int i = 0; i < n; i++) w.pb (gp (i));
    int ans = 1;
    for (int i = 0; i < n; i++)
        if (!was[gp (i)]) {
            if (go (gp (i), 0)) {
                ans = 0;
                break;
            }
            if (i != 0) ans = (ans * 2) % mod;
        }
    cout << ans << endl;
    return 0;
}


#include<iostream>
#include<algorithm>
#include<vector>

#define PB push_back

using namespace std;

const int MAXN = 100005, mod = 1e9 + 7;
int par[MAXN], h[MAXN], x[MAXN], y[MAXN], c[MAXN];
bool mark[MAXN];
vector<int> v[MAXN];

int getpar(int x)
{
	if(par[x] == -1)
		return x;
	return par[x] = getpar(par[x]);
}

void add(int x, int y)
{
	x = getpar(x), y = getpar(y);
	if(x == y)
		return;
	if(v[x].size() < v[y].size())
		swap(x, y);
	for(int z : v[y])
		v[x].PB(z);
	par[y] = x;
}

int DFS(int n)
{
	int ans = 2;
	mark[n] = true;
	for(int t : v[n])
	{
		int x = getpar(t);
		if(mark[x])
		{
			if(h[x] == h[n])
				return 0;
		}
		else
		{
			h[x] = !h[n];
			ans &= DFS(x);
		}
	}
	return ans;
}

int main()
{
	int n, m;
	cin >> n >> m;
	for(int i = 0; i < m; i++)
	{
		cin >> x[i] >> y[i] >> c[i];
		x[i]--, y[i]--;
		if(c[i] == 0)
		v[x[i]].PB(y[i]), v[y[i]].PB(x[i]);
	}
	fill(par, par + n, -1);
	for(int i = 0; i < m; i++)
		if(c[i] == 1)
			add(x[i], y[i]);
	int ans = 1;
	bool flag = false;
	for(int i = 0; i < n; i++)
		if(!mark[getpar(i)])
		{
			ans = ans * DFS(getpar(i)) % mod;
			if(!flag)
				flag = true, ans /= 2;
		}
	cout << ans << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <cstring>

#define si(a) scanf("%d",&a)
#define MAX 100005
#define s second
#define f first

using namespace std;

vector<pair<int,int> > graph[MAX];

int value[MAX];

void dfs(int from,int now,int v)
{
    value[now]=v;
    int i;
    for(i=0;i<graph[now].size();i++){
        if(graph[now][i].f==from)
            continue;
        if(value[graph[now][i].f]!=-1){
            if(value[graph[now][i].f]!=(v^(graph[now][i].s))){
                printf("0\n");
                exit(0);
            }
            continue;
        }
        dfs(now,graph[now][i].f,v^(graph[now][i].s));
    }
    return ;
}

long long bigmod ( long long a , long long b , int M)
{
    if ( b == 0 ) return 1 % M;
    long long x = bigmod ( a , b / 2 , M) ;
    x = ( x * x ) % M;
    if ( b % 2 ) x = ( x * a ) % M;
    return x ;
}

int main()
{

    //freopen("input.txt","r",stdin);
    int i,n,m;
    si(n);si(m);
    memset(value,-1,sizeof(value));
    for(i=0;i<m;i++){
        int a,b,c;
        si(a);si(b);si(c);
        a--;b--;
        graph[a].push_back({b,!c});
        graph[b].push_back({a,!c});
    }
    long long total=0;
    for(i=0;i<n;i++){
        if(value[i]!=-1)
            continue;
        dfs(-1,i,0);
        total++;
    }

    total--;

    printf("%I64d\n",bigmod(2,total,1000000007));
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define maxn 200100
#define P pair<int,int>
#define mod 1000000007
vector<P>g[maxn];
int n,m,cnt=-1;
int vis[maxn];
void no()
{
    puts("0");
    exit(0);
}
void dfs(int u)
{
    for(auto it:g[u])
    {
        int v=it.first,typ=it.second;
        if(!vis[v])
        {
            if(typ) vis[v]=vis[u];
            else vis[v]=3-vis[u];
            dfs(v);
        }
        else
        {
            if(typ&&vis[v]!=vis[u]) no();
            if(!typ&&vis[v]==vis[u]) no();
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        g[u].push_back(P(v,w));
        g[v].push_back(P(u,w));
    }
    for(int i=1;i<=n;++i)
    {
        if(!vis[i])
        {
            vis[i]=1;
            dfs(i);
            ++cnt;
        }
    }
    int ans=1;
    while(cnt--)
    {
        ans<<=1;
        if(ans>=mod) ans-=mod;
    }
    printf("%d\n",ans);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=200100;
int fa[maxn];
int find(int p)
{
    if(p==fa[p])
        return p;
    else
        return fa[p]=find(fa[p]);

}

void bin(int a,int b)
{

    int x1=find(a);
    int x2=find(b);
    if(x1!=x2)
        fa[x2]=x1;
}
typedef long long ll;

ll powermi(ll n,ll p)
{
    ll tt=n,k=1;
    ll ans=1;
    while(p)
    {

        if(p&1)
          ans=ans*tt%mod;
           p/=2;
     tt=tt*tt%mod;

    }
    return ans;

}

int main()
{
bool flag=false;
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=2*n;i++)
        fa[i]=i;

    for(int i=0;i<m;i++)
    {

        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        if(c==1)
        {
       if(find(a)==find(b+n)||find(b)==find(a+n))
        {flag=true;
        continue;
        }
 bin(a,b);
        bin(a+n,b+n);

        }
        else
        {
            if(find(a)==find(b)||find(a+n)==find(b+n))
            {
                flag=true;
                continue;
            }
            bin(a,b+n);
            bin(a+n,b);
        }

    }
    ll ans=1;
    if(flag)
       ans=0;
    ll cnt=0;
    for(int i=1;i<=2*n;i++)
    {
        if(fa[i]==i)
            cnt++;
    }
    cnt/=2;
    cnt--;
    ans=ans*powermi(2LL,cnt);
    cout<<ans<<endl;

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=100100;
int fa[maxn];
int find(int p)
{
    if(p==fa[p])
        return p;
    else
        return fa[p]=find(fa[p]);

}

void bin(int a,int b)
{

    int x1=find(a);
    int x2=find(b);
    if(x1!=x2)
        fa[x2]=x1;
}
typedef long long ll;

ll powermi(ll n,ll p)
{
    ll tt=n,k=1;
    ll ans=1;
    while(p)
    {

        if(p&1)
          ans=ans*tt%mod;
           p/=2;
     tt=tt*tt%mod;

    }
    return ans;

}

int main()
{
bool flag=false;
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=2*n;i++)
        fa[i]=i;

    for(int i=0;i<m;i++)
    {

        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        if(c==1)
        {
       if(find(a)==find(b+n)||find(b)==find(a+n))
        {flag=true;
        continue;
        }
 bin(a,b);
        bin(a+n,b+n);

        }
        else
        {
            if(find(a)==find(b)||find(a+n)==find(b+n))
            {
                flag=true;
                continue;
            }
            bin(a,b+n);
            bin(b,a+n);
        }

    }
    ll ans=1;
    if(flag)
       ans=0;
    ll cnt=0;
    for(int i=1;i<=n;i++)
    {
        if(fa[i]==i)
            cnt++;
    }
    cnt--;
    ans=ans*powermi(2LL,cnt);
    cout<<ans<<endl;

    return 0;
}


#include<iostream>
#include<cstdio>
using namespace std;
const int Maxn=1e5+100,mod=1e9+7;int n,m,f[2*Maxn];
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
void merge(int x,int y){x=find(x);y=find(y);if(x!=y)f[x]=y;}
int main(int argc, const char * argv[]) {
    ios::sync_with_stdio(0);
    int i;cin>>n>>m;
    for(i=1;i<=2*n;i++)f[i]=i;
    for(i=1;i<=m;i++){int a,b,c;cin>>a>>b>>c;if(c==1){if(find(a+n)==find(b)||find(b+n)==find(a)){puts("0");return 0;}merge(a,b);merge(a+n,b+n);}else{if(find(a)==find(b)||find(a+n)==find(b+n)){puts("0");return 0;}merge(a+n,b);merge(a,b+n);}}
    int cnt=0;for(i=1;i<=n;i++){
        if(f[i]==i)cnt++;}cnt--;
    int ans=1,base=2;while(cnt){if(cnt&1){ans=1LL*ans*base%mod;}
        base=1LL*base*base%mod;cnt>>=1;}
    printf("%d\n",ans);
    return 0;
}


#include<iostream>
#include<cstdio>
using namespace std;
const int Maxn=1e5+100,mod=1e9+7;int n,m,f[2*Maxn];
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
void merge(int x,int y){x=find(x);y=find(y);if(x!=y)f[x]=y;}
int main(int argc, const char * argv[]) {
    ios::sync_with_stdio(0);
    int i;cin>>n>>m;
    for(i=1;i<=2*n;i++)f[i]=i;
    for(i=1;i<=m;i++){int a,b,c;cin>>a>>b>>c;if(c==1){if(find(a+n)==find(b)||find(b+n)==find(a)){puts("0");return 0;}merge(a,b);merge(a+n,b+n);}else{if(find(a)==find(b)){puts("0");return 0;}merge(a+n,b);merge(a,b+n);}}
    int cnt=0;for(i=1;i<=n;i++){
        if(f[i]==i)cnt++;}cnt--;
    int ans=1,base=2;while(cnt){if(cnt&1){ans=1LL*ans*base%mod;}
        base=1LL*base*base%mod;cnt>>=1;}
    printf("%d\n",ans);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=100100;
int fa[maxn];
int find(int p)
{
    if(p==fa[p])
        return p;
    else
        return fa[p]=find(fa[p]);

}

void bin(int a,int b)
{

    int x1=find(a);
    int x2=find(b);
    if(x1!=x2)
        fa[x2]=x1;
}
typedef long long ll;

ll powermi(ll n,ll p)
{
    ll tt=n,k=1;
    ll ans=1;
    while(p)
    {

        if(p&1)
          ans=ans*tt%mod;
           p/=2;
     tt=tt*tt%mod;

    }
    return ans;

}

int main()
{
bool flag=false;
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=2*n;i++)
        fa[i]=i;

    for(int i=0;i<m;i++)
    {

        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        if(c==1)
        {
       if(find(a)==find(b+n)||find(b)==find(a+n))
        {flag=true;
        continue;
        }
 bin(a,b);
        bin(a+n,b+n);

        }
        else
        {
            if(find(a)==find(b)||find(a+n)==find(b+n))
            {
                flag=true;
                continue;
            }
            bin(a,b+n);
            bin(a+n,b);
        }

    }
    ll ans=1;
    if(flag)
       ans=0;
    ll cnt=0;
    for(int i=1;i<=2*n;i++)
    {
        if(fa[i]==i)
            cnt++;
    }
    cnt/=2;
    cnt--;
    ans=ans*powermi(2LL,cnt);
    cout<<ans<<endl;

    return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <cstring>

#define si(a) scanf("%d",&a)
#define MAX 100005
#define s second
#define f first

using namespace std;

vector<pair<int,int> > graph[MAX];

int value[MAX];

void dfs(int from,int now,int v)
{
    value[now]=v;
    int i;
    for(i=0;i<graph[now].size();i++){
        if(graph[now][i].f==from)
            continue;
        if(value[graph[now][i].f]!=-1){
            if(value[graph[now][i].f]!=(v^(graph[now][i].s))){
                printf("0\n");
                exit(0);
            }
            continue;
        }
        dfs(now,graph[now][i].f,v^(graph[now][i].s));
    }
    return ;
}

long long bigmod ( long long a , long long b , int M)
{
    if ( b == 0 ) return 1 % M;
    long long x = bigmod ( a , b / 2 , M) ;
    x = ( x * x ) % M;
    if ( b % 2 ) x = ( x * a ) % M;
    return x ;
}

int main()
{

    //freopen("input.txt","r",stdin);
    int i,n,m;
    si(n);si(m);
    memset(value,-1,sizeof(value));
    for(i=0;i<m;i++){
        int a,b,c;
        si(a);si(b);si(c);
        a--;b--;
        graph[a].push_back({b,c});
        graph[b].push_back({a,c});
    }
    long long total=0;
    for(i=0;i<n;i++){
        if(value[i]!=-1)
            continue;
        dfs(-1,i,0);
        total++;
    }

    total--;

    printf("%I64d\n",bigmod(2,total,1000000007));
    return 0;
}


#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <cstring>
#include <vector>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <iterator>

#pragma comment(linker, ”/STACK:36777216“)
#define mp make_pair
#define pb push_back
#define x first
#define y second
#define pii pair<int,int>
#define pdd pair<double,double>
#define FOR(i,a,b) for (int _n(b), i(a); i <= _n; ++i)
#define FORD(i,a,b) for(int i=(a),_b=(b);i >= _b; --i)
#define all(c) (c).begin(), (c).end()
#define SORT(c) sort(all(c))
#define rep(i,n) FOR(i,0,(n)-1)
#define VI vector <int>
#define ll long long
#define sqr(x) ((x)*(x))

int ddx[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
int ddy[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
int dx[] = { -1, 1, 0, 0 };
int dy[] = { 0, 0, -1, 1 };

using namespace std;

#define MOD 1000000007
#define R2 500000004
#define R3 333333336
#define INF 1000000000
#define EPS 1e-7
#define PI 3.1415926535897932384626433832795028841971
#define MAX 100011

VI g[3][MAX];
int ID[MAX];
int color[MAX];

void dfs(int v, int id)
{
	ID[v] = id;
	rep(i, g[0][v].size())
		if (!ID[g[0][v][i]])
			dfs(g[0][v][i], id);
}

bool dfs2(int v, int cur)
{
	if (color[v] == cur)return 1;
	if (color[v] != -1)return 0;
	color[v] = cur;
	bool ok = 1;
	rep(i, g[2][v].size())
		if (!dfs2(g[2][v][i], cur ^ 1))ok = 0;
	return ok;
}

int main()
{
	int n, m;
	cin >> n >> m;
	rep(i, m)
	{
		int a, b, c;
		cin >> a >> b >> c;
		--a, --b;
		g[c][a].pb(b);
		g[c][b].pb(a);
	}
	int id = 1;
	rep(i, n)
		if (!ID[i])
			dfs(i, id++);
	rep(i, n)
		rep(j, g[1][i].size())
		g[2][ID[g[1][i][j]]].pb(ID[i]),
		g[2][ID[i]].pb(ID[g[1][i][j]]);
	rep(i, id)
		color[i+1] = -1;
	int cmp = 0;
	FOR(i, 1, id - 1)
		if (color[i]==-1)
		{
			++cmp;
			if (!dfs2(i, 0))
			{
				cout << 0 << endl;
				return 0;
			}
		}
	ll ans = 1;
	rep(i, cmp - 1)
		ans <<= 1, ans %= MOD;
	cout << ans << endl;

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <cstring>
#include <vector>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <iterator>

#pragma comment(linker, ”/STACK:36777216“)
#define mp make_pair
#define pb push_back
#define x first
#define y second
#define pii pair<int,int>
#define pdd pair<double,double>
#define FOR(i,a,b) for (int _n(b), i(a); i <= _n; ++i)
#define FORD(i,a,b) for(int i=(a),_b=(b);i >= _b; --i)
#define all(c) (c).begin(), (c).end()
#define SORT(c) sort(all(c))
#define rep(i,n) FOR(i,0,(n)-1)
#define VI vector <int>
#define ll long long
#define sqr(x) ((x)*(x))

int ddx[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
int ddy[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
int dx[] = { -1, 1, 0, 0 };
int dy[] = { 0, 0, -1, 1 };

using namespace std;

#define MOD 1000000007
#define R2 500000004
#define R3 333333336
#define INF 1000000000
#define EPS 1e-7
#define PI 3.1415926535897932384626433832795028841971
#define MAX 100011

VI g[3][MAX];
int ID[MAX];
int color[MAX];

void dfs(int v, int id)
{
	ID[v] = id;
	rep(i, g[0][v].size())
		if (!ID[g[0][v][i]])
			dfs(g[0][v][i], id);
}

bool dfs2(int v, int cur)
{
	if (color[v] == cur)return 1;
	if (color[v] != -1)return 0;
	color[v] = cur;
	bool ok = 1;
	rep(i, g[2][v].size())
		if (!dfs2(g[2][v][i], cur ^ 1))ok = 0;
	return ok;
}

int main()
{
	int n, m;
	cin >> n >> m;
	rep(i, m)
	{
		int a, b, c;
		cin >> a >> b >> c;
		--a, --b;
		g[c^1][a].pb(b);
		g[c^1][b].pb(a);
	}
	int id = 1;
	rep(i, n)
		if (!ID[i])
			dfs(i, id++);
	rep(i, n)
		rep(j, g[1][i].size())
		g[2][ID[g[1][i][j]]].pb(ID[i]),
		g[2][ID[i]].pb(ID[g[1][i][j]]);
	rep(i, id)
		color[i+1] = -1;
	int cmp = 0;
	FOR(i, 1, id - 1)
		if (color[i]==-1)
		{
			++cmp;
			if (!dfs2(i, 0))
			{
				cout << 0 << endl;
				return 0;
			}
		}
	ll ans = 1;
	rep(i, cmp - 1)
		ans <<= 1, ans %= MOD;
	cout << ans << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <cstdio>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <cstring>
using namespace std;

const long long maxn = 1000000007LL;
int cnt = 0;
vector<int> g[100010];
bool v[100010];
int l[100010];
queue<int> q;

inline int sgn(int c) {
	// 1->1; 0->-1
	return 2*c-1;
}

void impos() {
	cout << 0;
	exit(0);
}

void bfs(int i) {
	q.push(i);
	v[i] = 1;
	while (!q.empty()) {
		int i = q.front();
		q.pop();
		for (auto j : g[i]) {
			int c;
			if (j>0) c = l[i];
			else c = !l[i];
			if (v[abs(j)]) {
				//cout << i << " " << j << " " << c << " " << l[abs(j)] << endl;
				if (c!=l[abs(j)]) impos();
			}
			else {
				l[abs(j)] = c;
				q.push(abs(j));
				v[abs(j)] = 1;
			}
		}
	}
}

int pow1(int n) {
	int ans = 1;
	for (int i = 0; i < n; ++i )
		ans = (ans*2) % maxn;
	return ans;
}

int main(int argc, char *argv[]) {
	//freopen("a.in", "r", stdin);
	//freopen("a.out", "w", stdout);
	int m;
	int n;
	cin >> n >> m;
	for (int i = 0; i < m; ++i ) {
		int a, b, c;
		cin >> a >> b >> c;
		g[a].push_back(sgn(c)*b);
		g[b].push_back(sgn(c)*a);
	}
	for (int i = 1; i <= n; ++i ) {
		if (!v[i]) {
			//cout << i << endl;
			++cnt;
			bfs(i);
		}
	}
	cout << pow1(cnt-1);
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int parent[100010];
int cc;
vector<int>G[100010];
int vis[100010];
const int MOD=1000000007;
int init(int n){
    for(int i=0;i<=n;i++)parent[i]=i;
    cc=n;
}
int find(int u){
    return u==parent[u]?u:parent[u]=find(parent[u]);
}
void _union(int u,int v){
    int pu=find(u),pv=find(v);
    if(pu!=pv){
        cc--;
        parent[pv]=pu;
    }
}
bool bipar(int u){
    vis[u]=1;
    queue<int>q;
    q.push(u);
    while(!q.empty()){
        u=q.front();
        q.pop();
        for(int v:G[u]){
            if(!vis[v]){
                vis[v]=(vis[u]==1?2:1);
                q.push(v);
            }
            else if(vis[u]==vis[v])return false;
        }
    }
    return true;
}
int main(){
    int n,m;
    cin>>n>>m;
    init(n);
    vector<pair<int,int> >vp;
    for(int i=0,u,v,w;i<m;i++){
        cin>>u>>v>>w;
        if(w)_union(u,v);
        else vp.push_back({u,v});
    }
    for(auto u:vp){
        G[find(u.first)].push_back(find(u.second));
        G[find(u.second)].push_back(find(u.first));
    }
    int ret=0;
    for(int i=1;i<=n;i++){
        if(!vis[i]&&find(i)==i)
            if(!bipar(i))return cout<<0,0;
            else {ret++;}
    }
    int ans=1;
    //cout<<cc<<" dat cc "<<endl;
    for(int i=1;i<ret;i++)ans*=2,ans%=MOD;
    cout<<ans%MOD;
}


#include <iostream>
#include <vector>
#include <queue>
using namespace std;
vector<int>G[100010];
int parent[100010],col[100010];
const int MOD=1e9+7;
vector<pair<int,int> >edges;

int find(int u){
    return u==parent[u]?u:parent[u]=find(parent[u]);
}
void _union(int u,int v){
    int pu=find(u),pv=find(v);
    if(pu!=pv){
        parent[pv]=pu;
    }
}
bool bicol(int u){
    col[u]=1;
    queue<int>q;
    q.push(u);
    while(!q.empty()){
        u=q.front();
        q.pop();
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(!col[v]){
                col[v]=3-col[u];
                q.push(v);
            }
            else if(col[u]==col[v])return false;
        }
    }
    return true;
}
int main(){
    int n,m;
    cin>>n>>m;
    for(int i=0;i<=n;i++)parent[i]=i;
    for(int i=0,u,v,w;i<m;i++){
        cin>>u>>v>>w;
        if(!w)edges.push_back({u,v});
        else _union(u,v);
    }
    for(int i=0;i<edges.size();i++){
        G[find(edges[i].first)].push_back(find(edges[i].second));
        G[find(edges[i].second)].push_back(find(edges[i].first));
    }
    int op=0;
    for(int i=1;i<=n;i++){
        if(!col[i]&&find(i)==i)
            if(!bicol(i))return cout<<0,0;
            else op++;
    }
    int ans=1;
    for(int i=1;i<op;i++)ans*=2,ans%=MOD;
    cout<<ans%MOD;
}


# include <iostream>
# include <sstream>
# include <cstdio>
# include <cstdlib>
# include <algorithm>
# include <string>
# include <cstring>
# include <cmath>
# include <stack>
# include <queue>
# include <vector>
# include <list>
# include <map>
# include <set>
# include <deque>
# include <iterator>
# include <functional>
# include <bitset>
# include <climits>
# include <ctime>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define odd(x) (x&1)
typedef long long ll;
typedef long double ld;
const ll oo = /*2 * 1000 * 1000 * 1000*/0x3f3f3f3f;
const int _cnt = 1000 * 1000;
const int _p = 1000 * 1000 * 1000 + 7;
//const int _p = 1007;
ll o(ll x) { return x%_p; }
int gcd(int a, int b) { return b ? gcd(b, a%b) : a; }
//ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; }
int lcm(int a, int b) { return a / gcd(a, b)*b; }
using namespace std;

void file_put() {
    freopen("filename.in", "r", stdin);
    freopen("filename.out", "w", stdout);
}

int n,m,home[500005],x,y,k,p,q,cnt=0;

int opposite(int k){
    if (k>n) return k-n; else return k+n;
}

bool oppo(int x,int y){
    return opposite(x)==y;
}

int _find(int x){
    if (home[x]==x) return x;
    return home[x]=_find(home[x]);
}

int main() {
    //file_put();

    scanf("%d%d",&n,&m);
    for (int i=1; i<=2*n; i++) home[i]=i;
    for (int i=1; i<=m; i++){
        scanf("%d%d%d",&x,&y,&k);
        p=_find(x);
        q=_find(y);
        if (k==1){
            if (p==q) continue;
            if (oppo(p,q)) return 0*printf("0\n");
            home[p]=q;
            home[opposite(p)]=opposite(q);
        }
        if (k==0){
            if (p==q) return 0*printf("0\n");
            if (oppo(p,q)) continue;
            home[p]=opposite(q);
            home[opposite(p)]=q;
        }
    }
    for (int i=1; i<=2*n; i++) cnt+=(home[i]==i);
    cnt/=2;
    ll ans=1;
    for (int i=1; i<=cnt-1; i++) ans=(ans*2)%_p;
    cout<<ans<<endl;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define se second
#define fi first
#define pb push_back
const int N=1e5 + 5,M=1e9 + 7;
int par[N],col[N],pw[N];
vector<int> g[N];
int fp(int u){
	return (par[u] == u) ? u : par[u]=fp(par[u]);
}

void dfs(int u){

	for(int i=0;i < g[u].size();i++){
		int v=g[u][i];
		if(!col[v]){
			col[v]=-col[u];
			dfs(v);
		}
		else if(col[v] == col[u]){
			puts("0");
			exit(0);
		}
	}
}

int main(){

//	freopen("in.txt","r",stdin);

	int n,m;
	scanf("%d%d",&n,&m);
	pw[0]=1;
	for(int i=1;i <= n;i++){
		par[i]=i;
		pw[i]=(pw[i - 1] * 2LL) % M;
	}
	vector<pair<int, int> > temp;
	for(int i=0,a,b,c;i < m;i++){
		scanf("%d%d%d",&a,&b,&c);
		if(!c){
			temp.pb({ a, b });
			continue;
		}
		par[fp(a)]=fp(b);
	}
	for(int i=0,a,b;i < temp.size();i++){
		a=fp(temp[i].fi);
		b=fp(temp[i].se);
		g[a].pb(b);
		g[b].pb(a);
	}
	int cmp=0;
	for(int i=1;i <= n;i++){
		if(fp(i) == i && !col[i]){
			cmp++;
			col[i]=1;
			dfs(i);
		}
	}
	cout << pw[cmp - 1] << endl;

}


#include <cstdio>
#include <vector>

typedef long long int lli;

const int MAX = 100005;
const lli MOD = 1000000007;

std::vector<int> v[MAX];

int rem[MAX][2];
int num[MAX];

void dfs(int x, int l)
{
	if (num[x]!=0)
		return;
	num[x]=l;
	for (int a : v[x])
		dfs(a, l);
}

lli pot(lli a, int n)
{
	if (n==0)
		return 1LL;
	if (n&1)
		return (a*pot(a, n-1))%MOD;
	return pot((a*a)%MOD, n/2);
}

struct par
{
	int a;
	int b;
};

bool operator<(par a, par b)
{
	if (a.a==b.a)
		return a.b<b.b;
	return a.a<b.a;
}

std::vector<int> fin[MAX];

int id[MAX];

bool dfs2(int x, int l)
{
	if (id[x]==3-l)
		return 0;
	if (id[x]==l)
		return 1;
	id[x]=l;

	for (int a : fin[x]) {
		if (!dfs2(a, 3-l))
			return 0;
	}

	return 1;
}

int main()
{
	int n, m, a, b, c, l=0;
	scanf("%d%d", &n, &m);
	for (int i=0; i<m; i++) {
		scanf("%d%d%d", &a, &b, &c);
		if (c==1) {
			v[a].push_back(b);
			v[b].push_back(a);
		}
		if (c==0) {
			rem[l][0]=a;
			rem[l][1]=b;
			l++;
		}
	}

	int lic=0;

	for (int i=1; i<=n; i++) {
		if (num[i]==0) {
			lic++;
			dfs(i, lic);
		}
	}

	for (int i=0; i<l; i++) {
		a=num[rem[i][0]];
		b=num[rem[i][1]];

		fin[a].push_back(b);
		fin[b].push_back(a);
	}

	int tmp=0;

	for (int i=1; i<=lic; i++) {
		if (id[i]==0) {
			if (!dfs2(i, 1)) {
				printf("0\n");
				return 0;
			}
			tmp++;
		}
	}

	printf("%d\n", (int)pot(2LL, tmp-1));

	return 0;
}
//ADG


// IN THE NAME OF ALLAH
#include <math.h>
#include <vector>
#include <set>
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <map>
#include <queue>
#include <stack>
#include<cstring>
#include <cstdlib>
#include <string>
#include <ctime>
#include <cstdio>
#include <cmath>
#include <unordered_map>
#include <unordered_set>
#include <bitset>

#define F first
#define S second
#define mp make_pair
#define L(x) (2*(x))
#define R(x) ((2*(x))+1)
#define pii pair<int , int>

using namespace std;
typedef long long ll;

const int N = 5e6 + 5, Mod = 1e9 + 7, MAXN = 3e5 + 10, LG = 20 , M = 1e9, P = 727, Sq = 550;
const ll inf = 3e18 + 10;

int red[N], blue[N], pw[N], cnt = 0, n, m;
vector< int > b[N], r[N], adj[N];
map< pair< int, int >, int > mm;

void predfs(int u){
      red[u] = cnt;
      for(int i = 0; i < (int)r[u].size(); i++)
            if(!red[r[u][i]])
                  predfs(r[u][i]);
}
void Check(int u){
      if(!blue[u])
            blue[u] = 1;
      for(int i = 0; i < (int)adj[u].size(); i++){
            if(blue[adj[u][i]] == blue[u]){
                  cout << 0;
                  exit(0);
            }
            if(!blue[adj[u][i]]){
                  blue[adj[u][i]] = 3 - blue[u];
                  Check(adj[u][i]);
            }
      }
}
int main(){
      ios_base::sync_with_stdio(0); cin.tie(0);
      pw[0] = 1;
      for(int i = 1; i < N; i++)
            pw[i] = 1ll * pw[i - 1] * 2 % Mod;
      cin >> n >> m;
      for(int i = 1; i <= m; i++){
            int x, y, z; cin >> x >> y >> z;
            if(z)
                  r[x].push_back(y), r[y].push_back(x);
            else
                  b[x].push_back(y), b[y].push_back(x);
      }
      for(int i = 1; i <= n; i++)
            if(!red[i])
                  cnt++, predfs(i);
      for(int i = 1; i <= n; i++)
            for(int j = 0; j < (int)b[i].size(); j++)
                  if(red[i] == red[b[i][j]] && red[i])
                        return cout << 0, 0;
      for(int i = 1; i <= n; i++){
            for(int j = 0; j < (int)b[i].size(); j++){
                  int x = red[i], y = red[b[i][j]];
                  if(x > y)
                        swap(x, y);
                  if(!mm[mp(x, y)]){
                        mm[mp(x, y)] = 1;
                        adj[x].push_back(y);
                        adj[y].push_back(x);
                  }
            }
      }
      int num = 0;
      for(int i = 1; i <= cnt; i++){
            if(!blue[i]){
                  Check(i);
                  num++;
            }
      }
      return cout << pw[num - 1], 0;
}//hellobig_tq//hello


//God & me
#include <bits/stdc++.h>
#define pb push_back
#define X first
#define Y second
#define int long long
using namespace std;
template<class T,class L>bool smax(T&x,L y){return x<y?(x=y,1):0;}template<class T,class L>bool smin(T&x,L y){return x>y?(x=y,1):0;}
typedef pair<int,int> pii;
const int maxn=1e5+17,mod=1e9+17-10;
int n,m,cnt;
vector<int>l[maxn],h[maxn],g[maxn];
int mark[maxn];
void dfs(int v){
  mark[v]=cnt;
  for(auto u:l[v])
    if(mark[u]==-1)
      dfs(u);
  for(auto u:h[v])
    g[cnt].pb(u);
}
void check(int v,int cl=0){
  mark[v]=cl;
  for(auto u:g[v])
    if(mark[u]==mark[v])
      cout<<"0\n",exit(0);
    else if(mark[u]==-1)
      check(u,cl^1);
}
main(){
  ios::sync_with_stdio(0),cin.tie();
  cin>>n>>m;
  for(int v,u,t;m--;){
    cin>>v>>u>>t;
    if(t)
      l[--v].pb(--u),l[u].pb(v);
    else
      h[--v].pb(--u),h[u].pb(v);
  }
  memset(mark,-1,sizeof mark);
  for(int i=0;i<n;i++)
    if(mark[i]==-1){
      dfs(i);
      cnt++;
    }
  for(int i=0;i<n;i++){
    for(auto &x:g[i])
      x=mark[x];
    sort(g[cnt].begin(),g[cnt].end());
    g[cnt].resize(unique(g[cnt].begin(),g[cnt].end())-g[cnt].begin());
  }
  memset(mark,-1,sizeof mark);
  int p=0,ans=1;
  for(int i=0;i<cnt;i++)
    if(mark[i]==-1)
      check(i),p++;
  p--;
  for(int a=2;p;p>>=1)
    ans*=(p&1?a:1),a*=a,a%=mod,ans%=mod;
  cout<<ans<<'\n';
  return 0;
}


// IN THE NAME OF ALLAH
#include <math.h>
#include <vector>
#include <set>
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <map>
#include <queue>
#include <stack>
#include<cstring>
#include <cstdlib>
#include <string>
#include <ctime>
#include <cstdio>
#include <cmath>
#include <unordered_map>
#include <unordered_set>
#include <bitset>

#define F first
#define S second
#define mp make_pair
#define L(x) (2*(x))
#define R(x) ((2*(x))+1)
#define pii pair<int , int>

using namespace std;
typedef long long ll;

const int N = 5e6 + 5, Mod = 1e9 + 7, MAXN = 3e5 + 10, LG = 20 , M = 1e9, P = 727, Sq = 550;
const ll inf = 3e18 + 10;

int red[N], blue[N], pw[N], cnt = 0, n, m;
vector< int > b[N], r[N], adj[N];
map< pair< int, int >, int > mm;

void predfs(int u){
      red[u] = cnt;
      for(int i = 0; i < (int)r[u].size(); i++)
            if(!red[r[u][i]])
                  predfs(r[u][i]);
}
void Check(int u){
      if(!blue[u])
            blue[u] = 1;
      for(int i = 0; i < (int)adj[u].size(); i++){
            if(blue[adj[u][i]] == blue[u]){
                  cout << 0;
                  exit(0);
            }
            if(!blue[adj[u][i]]){
                  blue[adj[u][i]] = 3 - blue[u];
                  Check(adj[u][i]);
            }
      }
}
int main(){
      ios_base::sync_with_stdio(0); cin.tie(0);
      pw[0] = 1;
      for(int i = 1; i < N; i++)
            pw[i] = 1ll * pw[i - 1] * 2 % Mod;
      cin >> n >> m;
      for(int i = 1; i <= m; i++){
            int x, y, z; cin >> x >> y >> z;
            if(z)
                  r[x].push_back(y), r[y].push_back(x);
            else
                  b[x].push_back(y), b[y].push_back(x);
      }
      for(int i = 1; i <= n; i++)
            if(!red[i])
                  cnt++, predfs(i);
      for(int i = 1; i <= n; i++)
            for(int j = 0; j < (int)b[i].size(); j++)
                  if(red[i] == red[b[i][j]] && red[i])
                        return cout << 0, 0;
      for(int i = 1; i <= n; i++){
            for(int j = 0; j < (int)b[i].size(); j++){
                  int x = red[i], y = red[b[i][j]];
                  if(x > y)
                        swap(x, y);
                  if(!mm[mp(x, y)]){
                        mm[mp(x, y)] = 1;
                        adj[x].push_back(y);
                        adj[y].push_back(x);
                  }
            }
      }
      int num = 0;
      for(int i = 1; i <= cnt; i++){
            if(!blue[i]){
                  Check(i);
                  num++;
            }
      }
      return cout << pw[num - 1], 0;
}//hellobig_tq//hello//hello


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int INF=1011110000,MOD=1000000007;
typedef long long LL;
int n,m;
vector<int> bad[101111], gd[101111], G[101111];
int gid[101111],clr[101111];
bool vst[101111];

void dfs(int v, int id){
    if(gid[v]!=-1)return;
    gid[v]=id;
    for(int u:gd[v]) dfs(u,id);
}

bool dfsc(int v, int c){
    if(clr[v]!=-1){
        return clr[v]==c;
    }
    clr[v]=c;
    for(int u:G[v]){
        if(dfsc(u,1-c)==0)return 0;
    }
    return 1;
}
void input(){
    cin>>n>>m;
    for(int i=0,a,b,c; i<m; i++){
        scanf("%d%d%d",&a,&b,&c);
        a--,b--;
        if(c){
            gd[a].push_back(b);
            gd[b].push_back(a);
        }else{
            bad[a].push_back(b);
            bad[b].push_back(a);
        }
    }
}

void solve(){
    memset(gid,-1,sizeof(gid));
    int nc=0;
    for(int i=0; i<n; i++){
        if(gid[i]==-1){
            dfs(i,nc);
            nc++;
        }
    }
    // printf("nc=%d\n",nc);
    for(int v=0; v<n; v++){
        for(int u:bad[v]){
            G[gid[v]].push_back(gid[u]);
            // printf("%d-%d\n",gid[v],gid[u]);
        }
    }
    int res=0;
    memset(clr,-1,sizeof(clr));

    for(int i=0,cnt=0; i<nc; i++){
        if(clr[i]==-1){
            if(!dfsc(i,0)){
                printf("0\n");
                return;
            }
            res++;
        }
    }
    LL pres=1;
    for(int i=0; i<res-1;i++){
        pres=pres*2%MOD;
    }
    cout<<pres<<endl;
}
int main(){
    // for(int i=0; i<11; i++){
    //     for(int j=0; j<=i; j++){
    //         printf("%lld ",ch[i][j]);
    //     }
    //     printf("\n");
    // }
    int t=1;
    // scanf("%d",&t);
    while(t--){
        input();
        solve();
    }
}
/*

15 7
8 8 U
6 10 L
9 7 L
3 13 L
15 1 L
13 3 U
1 15 L

*/


#define _CRT_SECURE_NO_WARNINGS
#include <fstream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <climits>
#include <map>
#include <iterator>
#include <queue>
#define mp make_pair
#define pb push_back
#define nfor(i, x, y) for (int i = x; i < y; i++)
#define si(n) scanf("%d", &n)
#define pi(n) printf("%d", n)

const int inf = 1000000007;

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef map<int, int> mii;
typedef map<int, bool> mib;
typedef pair<ll, ll> pll;
typedef vector<vector<int>> vvi;
typedef vector<int> vi;
typedef vector<bool> vb;

vector <vector <pii>> a;
vector <int> used;

void stop()
{
	puts("0");
	exit(0);
}

void dfs(int v)
{
	nfor(i, 0, a[v].size())
	{
		if (used[a[v][i].first] == -1)
		{
			if (a[v][i].second) used[a[v][i].first] = used[v];
			else used[a[v][i].first] = !used[v];
			dfs(a[v][i].first);
		}
		if (a[v][i].second && used[a[v][i].first] != used[v]) stop();
		if (!a[v][i].second && used[a[v][i].first] == used[v]) stop();
	}
}

int main()
{
#ifdef _DEBUG
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#else
	/*freopen("sum2.in", "r", stdin);
	freopen("sum2.out", "w", stdout);*/
#endif
	int n, m;
	si(n); si(m);
	a.resize(n);
	used.resize(n, -1);
	nfor(i, 0, m)

	{
		int t1, t2, t3;
		si(t1); si(t2); si(t3);
		t1--; t2--;
		a[t1].pb(mp(t2, t3));
		a[t2].pb(mp(t1, t3));
	}
	int ans = 1;
	nfor(i, 0, n)
	{
		if (used[i] == -1)
		{
			used[i] = 0;
			dfs(i);
			if (i) ans <<= 1, ans %= inf;
		}
	}
	pi(ans);
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <fstream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <climits>
#include <map>
#include <iterator>
#include <queue>
#define mp make_pair
#define pb push_back
#define nfor(i, x, y) for (int i = x; i < y; i++)
#define si(n) scanf("%d", &n)
#define pi(n) printf("%d", &n)

const int inf = 1000000007;

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef map<int, int> mii;
typedef map<int, bool> mib;
typedef pair<ll, ll> pll;
typedef vector<vector<int>> vvi;
typedef vector<int> vi;
typedef vector<bool> vb;

vector <vector <pii>> a;
vector <int> used;

void stop()
{
	puts("0");
	exit(0);
}

void dfs(int v)
{
	nfor(i, 0, a[v].size())
	{
		if (used[a[v][i].first] == -1)
		{
			if (a[v][i].second) used[a[v][i].first] = used[v];
			else used[a[v][i].first] = !used[v];
			dfs(a[v][i].first);
		}
		if (a[v][i].second && used[a[v][i].first] != used[v]) stop();
		if (!a[v][i].second && used[a[v][i].first] == used[v]) stop();
	}
}

int main()
{
#ifdef _DEBUG
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#else
	/*freopen("sum2.in", "r", stdin);
	freopen("sum2.out", "w", stdout);*/
#endif
	int n, m;
	si(n); si(m);
	a.resize(n);
	used.resize(n, -1);
	nfor(i, 0, m)

	{
		int t1, t2, t3;
		si(t1); si(t2); si(t3);
		t1--; t2--;
		a[t1].pb(mp(t2, t3));
		a[t2].pb(mp(t1, t3));
	}
	int ans = 1;
	nfor(i, 0, n)
	{
		if (used[i] == -1)
		{
			used[i] = 0;
			dfs(i);
			if (i) ans <<= 1, ans %= inf;
		}
	}
	pi(ans);
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <fstream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <climits>
#include <map>
#include <iterator>
#include <queue>
#define mp make_pair
#define pb push_back
#define nfor(i, x, y) for (int i = x; i < y; i++)
//#define sl(n) scanf("%lld", &n)
//#define pl(n) printf("%lld", &n)

const int inf = 1000000007;

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef map<int, int> mii;
typedef map<int, bool> mib;
typedef pair<ll, ll> pll;
typedef vector<vector<int>> vvi;
typedef vector<int> vi;
typedef vector<bool> vb;

vector <vector <pii>> a;
vector <int> used;

void stop()
{
	puts("0");
	exit(0);
}

void dfs(int v)
{
	nfor(i, 0, a[v].size())
	{
		if (used[a[v][i].first] == -1)
		{
			if (a[v][i].second) used[a[v][i].first] = used[v];
			else used[a[v][i].first] = !used[v];
			dfs(a[v][i].first);
		}
		if (a[v][i].second && used[a[v][i].first] != used[v]) stop();
		if (!a[v][i].second && used[a[v][i].first] == used[v]) stop();
	}
}

int main()
{
#ifdef _DEBUG
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#else
	/*freopen("sum2.in", "r", stdin);
	freopen("sum2.out", "w", stdout);*/
#endif
	int n, m;
	cin >> n >> m;
	a.resize(n);
	used.resize(n, -1);
	nfor(i, 0, m)

	{
		int t1, t2, t3;
		cin >> t1 >> t2 >> t3;
		t1--; t2--;
		a[t1].pb(mp(t2, t3));
		a[t2].pb(mp(t1, t3));
	}
	int ans = 1;
	nfor(i, 0, n)
	{
		if (used[i] == -1)
		{
			used[i] = 0;
			dfs(i);
			if (i) ans <<= 1, ans %= inf;
		}
	}
	cout << ans;
	return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

#define FU(i, a, b) for(decltype(b) i = (a); i < (b); ++i)
#define fu(i, n) FU(i, 0, n)

#define pb push_back
#define sz(c) int((c).size())

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef long long ll;
typedef vector<ll> vll;
typedef vector<pair<int, int> > vpi;

int L[100010];

ll power(ll a, ll b, ll mod){
    if(b==0) return 1;
    ll x = power(a, b/2, mod);
    if(b%2==0) return (x*x)%mod;
    else return (((a*x) % mod)*x)%mod;
}

bool doit(int v, vvi& edges, vi& mark, int g){
    mark[v] = g;
    for(int a : edges[v]){
        if(mark[a] == mark[v]) return false;
        if(!mark[a]) doit(a, edges, mark, 1+g%2);
    }
    return true;
}

int rep(int x){
    return x == L[x] ? x : L[x] = rep(L[x]);
}

void unio(int a, int b, int numrep){
    a = rep(a);
    b = rep(b);
    if(a!=b){
        if(b < a) swap(a,b);
        numrep--;
        L[b] = a;
    }
}

int main(){
    int P = 1000000007;
    int N, M, a, b, c;
    scanf("%d %d", &N, &M);
    vpi bad;
    vvi edges(N);
    vi mark(N);
    int numrep = N;
    fu(i, N) L[i] = i;
    fu(i, M){
        scanf("%d %d %d", &a, &b, &c);
        a--; b--;
        if(c==1) unio(a, b, numrep);
        else bad.pb({a, b});
    }
    int B = sz(bad);
    bool badflag = false;
    int x, y;
    fu(i, B){
        a = rep(bad[i].first);
        b = rep(bad[i].second);
        if(a == b){
            printf("0");
            return 0;
        }
        edges[a].pb(b);
        edges[b].pb(a);
        if(!badflag){
            x = a;
            y = b;
            badflag = true;
        }
    }
    if(!badflag){
        printf("%I64d", power(2, numrep - 1, P));
        return 0;
    }
    if(!doit(x, edges, mark, 1)){
        printf("0");
        return 0;
    }
    ll ans = 1;
    fu(i, N) if(!mark[rep(i)]){
        ans = (2*ans)%P;
        bool q = doit(rep(i), edges, mark, 1);
        if(!q){
            printf("0");
            return 0;
        }
        printf("%d, mark = %d\n", rep(i), mark[rep(i)]);
    }
    printf("%I64d", ans);
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

#define FU(i, a, b) for(decltype(b) i = (a); i < (b); ++i)
#define fu(i, n) FU(i, 0, n)

#define pb push_back
#define sz(c) int((c).size())

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef long long ll;
typedef vector<ll> vll;
typedef vector<pair<int, int> > vpi;

int L[100010];

ll power(ll a, ll b, ll mod){
    if(b==0) return 1;
    ll x = power(a, b/2, mod);
    if(b%2==0) return (x*x)%mod;
    else return (((a*x) % mod)*x)%mod;
}

struct UF{
    vi p, rank;

};

bool doit(int v, vvi& edges, vi& mark, int g){
    mark[v] = g;
    for(int a : edges[v]){
        if(mark[a] == mark[v]) return false;
        if(!mark[a]) doit(a, edges, mark, 1+g%2);
    }
    return true;
}

int rep(int x){
    return x == L[x] ? x : L[x] = rep(L[x]);
}

void unio(int a, int b, int numrep){
    a = rep(a);
    b = rep(b);
    if(a!=b){
        if(b < a) swap(a,b);
        numrep--;
        L[b] = a;
    }

}

int main(){
    int P = 1000000007;
    int N, M, a, b, c;
    scanf("%d %d", &N, &M);
    vpi bad;
    vvi edges(N);
    vi mark(N);
    int numrep = N;
    fu(i, N) L[i] = i;
    fu(i, M){
        scanf("%d %d %d", &a, &b, &c);
        a--; b--;
        if(c==1) unio(a, b, numrep);
        else bad.pb({a, b});
    }
    int B = sz(bad);
    bool badflag = false;
    int x, y;
    fu(i, B){
        a = rep(bad[i].first);
        b = rep(bad[i].second);
        if(a == b){
            printf("0");
            return 0;
        }
        edges[a].pb(b);
        edges[b].pb(a);
        if(!badflag){
            x = a;
            y = b;
            badflag = true;
        }
    }
    if(!badflag){
        printf("%I64d", power(2, numrep - 1, P));
        return 0;
    }
    doit(x, edges, mark, 1);
    ll ans = 1;
    fu(i, N) if(!mark[rep(i)]){
        ans = (2*ans)%P;
        bool q = doit(rep(i), edges, mark, 1);
        if(!q){
            printf("0");
            return 0;
        }
    }
    printf("%I64d", ans);

}


#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

#define FU(i, a, b) for(decltype(b) i = (a); i < (b); ++i)
#define fu(i, n) FU(i, 0, n)

#define pb push_back
#define sz(c) int((c).size())

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef long long ll;
typedef vector<ll> vll;
typedef vector<pair<int, int> > vpi;

int L[100010];

ll power(ll a, ll b, ll mod){
    if(b==0) return 1;
    ll x = power(a, b/2, mod);
    if(b%2==0) return (x*x)%mod;
    else return (((a*x) % mod)*x)%mod;
}

struct UF{
    vi p, rank;

};

bool doit(int v, vvi& edges, vi& mark, int g){
    mark[v] = g;
    for(int a : edges[v]){
        if(mark[a] == mark[v]) return false;
        if(!mark[a]) doit(a, edges, mark, 1+g%2);
    }
    return true;
}

int rep(int x){
    return x == L[x] ? x : L[x] = rep(L[x]);
}

void unio(int a, int b, int numrep){
    a = rep(a);
    b = rep(b);
    if(a!=b){
        if(b < a) swap(a,b);
        numrep--;
        L[b] = a;
    }

}

int main(){
    int P = 1000000007;
    int N, M, a, b, c;
    scanf("%d %d", &N, &M);
    vpi bad;
    vvi edges(N);
    vi mark(N);
    int numrep = N;
    fu(i, N) L[i] = i;
    fu(i, M){
        scanf("%d %d %d", &a, &b, &c);
        a--; b--;
        if(c==1) unio(a, b, numrep);
        else bad.pb({a, b});
    }
    int B = sz(bad);
    bool badflag = false;
    int x, y;
    fu(i, B){
        a = rep(bad[i].first);
        b = rep(bad[i].second);
        if(a == b){
            printf("0");
            return 0;
        }
        edges[a].pb(b);
        edges[b].pb(a);
        if(!badflag){
            a = x;
            b = y;
            badflag = true;
        }
    }
    if(!badflag){
        printf("%I64d", power(2, numrep - 1, P));
        return 0;
    }
    doit(x, edges, mark, 1);
    ll ans = 1;
    fu(i, N) if(!mark[rep(i)]){
        ans = (2*ans)%P;
        doit(i, edges, mark, 1);
    }
    printf("%I64d", ans);

}


#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

#define FU(i, a, b) for(decltype(b) i = (a); i < (b); ++i)
#define fu(i, n) FU(i, 0, n)

#define pb push_back
#define sz(c) int((c).size())

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef long long ll;
typedef vector<ll> vll;
typedef vector<pair<int, int> > vpi;

int L[100010];

ll power(ll a, ll b, ll mod){
    if(b==0) return 1;
    ll x = power(a, b/2, mod);
    if(b%2==0) return (x*x)%mod;
    else return (((a*x) % mod)*x)%mod;
}

bool doit(int v, vvi& edges, vi& mark, int g){
    mark[v] = g;
    for(int a : edges[v]){
        if(mark[a] == mark[v]) return false;
        if(!mark[a]) doit(a, edges, mark, 1+g%2);
    }
    return true;
}

int rep(int x){
    return x == L[x] ? x : L[x] = rep(L[x]);
}

void unio(int a, int b, int numrep){
    a = rep(a);
    b = rep(b);
    if(a!=b){
        if(b < a) swap(a,b);
        numrep--;
        L[b] = a;
    }
}

int main(){
    int P = 1000000007;
    int N, M, a, b, c;
    scanf("%d %d", &N, &M);
    vpi bad;
    vvi edges(N);
    vi mark(N);
    int numrep = N;
    fu(i, N) L[i] = i;
    fu(i, M){
        scanf("%d %d %d", &a, &b, &c);
        a--; b--;
        if(c==1) unio(a, b, numrep);
        else bad.pb({a, b});
    }
    int B = sz(bad);
    bool badflag = false;
    int x, y;
    fu(i, B){
        a = rep(bad[i].first);
        b = rep(bad[i].second);
        if(a == b){
            printf("0");
            return 0;
        }
        edges[a].pb(b);
        edges[b].pb(a);
        if(!badflag){
            x = a;
            y = b;
            badflag = true;
        }
    }
    if(!badflag){
        printf("%I64d", power(2, numrep - 1, P));
        return 0;
    }
    if(!doit(x, edges, mark, 1)){
        printf("0");
        return 0;
    }
    ll ans = 1;
    fu(i, N) if(!mark[rep(i)]){
        ans = (2*ans)%P;
        bool q = doit(rep(i), edges, mark, 1);
        if(!q){
            printf("0");
            return 0;
        }
    }
    printf("%I64d", ans);
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

#define FU(i, a, b) for(decltype(b) i = (a); i < (b); ++i)
#define fu(i, n) FU(i, 0, n)

#define pb push_back
#define sz(c) int((c).size())

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef long long ll;
typedef vector<ll> vll;
typedef vector<pair<int, int> > vpi;

int L[100010];

ll power(ll a, ll b, ll mod){
    if(b==0) return 1;
    ll x = power(a, b/2, mod);
    if(b%2==0) return (x*x)%mod;
    else return (((a*x) % mod)*x)%mod;
}

bool doit(int v, vvi& edges, vi& mark, int g){
    mark[v] = g;
    for(int a : edges[v]){
        if(mark[a] == mark[v]) return false;
        if(!mark[a]) if(!doit(a, edges, mark, 1+g%2)) return false;
    }
    return true;
}

int rep(int x){
    return x == L[x] ? x : L[x] = rep(L[x]);
}

void unio(int a, int b, ll& numrep){
    a = rep(a);
    b = rep(b);
    if(a!=b){
        if(b < a) swap(a,b);
        numrep--;
        L[b] = a;
    }
}

int main(){
    int P = 1000000007;
    int N, M, a, b, c;
    scanf("%d %d", &N, &M);
    vpi bad;
    vvi edges(N);
    vi mark(N);
    ll numrep = N;
    fu(i, N) L[i] = i;
    fu(i, M){
        scanf("%d %d %d", &a, &b, &c);
        a--; b--;
        if(c==1) unio(a, b, numrep);
        else bad.pb({a, b});
    }
    int B = sz(bad);
    bool badflag = false;
    int x, y;
    fu(i, B){
        a = rep(bad[i].first);
        b = rep(bad[i].second);
        if(a == b){
            printf("0");
            return 0;
        }
        edges[a].pb(b);
        edges[b].pb(a);
        if(!badflag){
            x = a;
            y = b;
            badflag = true;
        }
    }
    if(!badflag){

        printf("%I64d", power(2, numrep - 1, P));
        return 0;
    }
    if(!doit(x, edges, mark, 1)){
        printf("0");
        return 0;
    }
    ll ans = 1;
    fu(i, N) if(!mark[rep(i)]){
        ans = (2*ans)%P;
        bool q = doit(rep(i), edges, mark, 1);
        if(!q){
            printf("0");
            return 0;
        }
    }
    printf("%I64d", ans);
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

#define FU(i, a, b) for(decltype(b) i = (a); i < (b); ++i)
#define fu(i, n) FU(i, 0, n)

#define pb push_back
#define sz(c) int((c).size())

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef long long ll;
typedef vector<ll> vll;
typedef vector<pair<int, int> > vpi;

int L[100010];

ll power(ll a, ll b, ll mod){
    if(b==0) return 1;
    ll x = power(a, b/2, mod);
    if(b%2==0) return (x*x)%mod;
    else return (((a*x) % mod)*x)%mod;
}

bool doit(int v, vvi& edges, vi& mark, int g){
    mark[v] = g;
    for(int a : edges[v]){
        if(mark[a] == mark[v]) return false;
        if(!mark[a]) doit(a, edges, mark, 1+g%2);
    }
    return true;
}

int rep(int x){
    return x == L[x] ? x : L[x] = rep(L[x]);
}

void unio(int a, int b, ll& numrep){
    a = rep(a);
    b = rep(b);
    if(a!=b){
        if(b < a) swap(a,b);
        numrep--;
        L[b] = a;
    }
}

int main(){
    int P = 1000000007;
    int N, M, a, b, c;
    scanf("%d %d", &N, &M);
    vpi bad;
    vvi edges(N);
    vi mark(N);
    ll numrep = N;
    fu(i, N) L[i] = i;
    fu(i, M){
        scanf("%d %d %d", &a, &b, &c);
        a--; b--;
        if(c==1) unio(a, b, numrep);
        else bad.pb({a, b});
    }
    int B = sz(bad);
    bool badflag = false;
    int x, y;
    fu(i, B){
        a = rep(bad[i].first);
        b = rep(bad[i].second);
        if(a == b){
            printf("0");
            return 0;
        }
        edges[a].pb(b);
        edges[b].pb(a);
        if(!badflag){
            x = a;
            y = b;
            badflag = true;
        }
    }
    if(!badflag){

        printf("%I64d", power(2, numrep - 1, P));
        return 0;
    }
    if(!doit(x, edges, mark, 1)){
        printf("0");
        return 0;
    }
    ll ans = 1;
    fu(i, N) if(!mark[rep(i)]){
        ans = (2*ans)%P;
        bool q = doit(rep(i), edges, mark, 1);
        if(!q){
            printf("0");
            return 0;
        }
    }
    printf("%I64d", ans);
}


///in his name! hi again :P :D :) nothing bad has happened yet :) :| and FYI i think i love Toktam! nice guy :)
///today is 6,8,94
#include <iostream>
#include <vector>
#include <algorithm>
#define pb push_back
#define F first
#define S second
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;

const int maxn = 1e5 + 10;
const ll mod = 1e9 + 7;
int n, m, mark[maxn], color[maxn], col = 0, ted = 0, ans;
vector <pii> hate;
vector <int> G[maxn], Gp[maxn], Gz[maxn];
ll tav(int b){
    if (b < 0)
        return 0;
    ll ans = 1ll;
    for (int i = 0; i < b; i++){
        ans *= 2ll;
        ans %= 1ll * mod;
    }
    return ans;
}
void dfs(int u){
    color[u] = col;
    for (int i = 0; i < G[u].size(); i++)
        if (color[G[u][i]] == 0)
            dfs(G[u][i]);
    return;
}
bool dfsp(int u, int par){
    mark[u] = ted + par;
    for (int i = 0; i < Gp[u].size(); i++){
        if (!mark[Gp[u][i]]){
            if(dfsp(Gp[u][i], 1 - par))
                return 1;
        }
        else if (mark[Gp[u][i]] != ted + 1 - par)
            return 1;
    }
    return 0;
}
void prep(int u){
    sort(Gz[u].begin(), Gz[u].end());
    int i = 0;
    while(i < Gz[u].size()){
        Gp[u].pb(Gz[u][i]);
        while(i + 1 < Gz[u].size() && Gz[u][i + 1] == Gz[u][i]) i++;
        i++;
    }
}
bool bad(){
    for (int i = 0; i < hate.size(); i++){
        int u = hate[i].F, v = hate[i].S;
        if (color[u] == color[v])
            return 1;
        Gz[color[u]].pb(color[v]);
        Gz[color[v]].pb(color[u]);
    }
    for (int i = 1; i <= col; i++)
        prep(i);
    for (int i = 1; i <= col; i++){
        if (!mark[i]){
            ted += 2;
            ans++;
            if (dfsp(i, 0)){
                return 1;
            }
        }
    }
    return 0;
}
int main(){
    cin >> n >> m;
    for (int i = 0; i < m; i++){
        int u, v, w;
        cin >> u >> v >> w;     u--, v--;
        if (w){ /// in love :
            G[u].pb(v), G[v].pb(u);
        }else{ /// hate :
            hate.pb(pii(u, v));
        }
    }
    for (int i = 0; i < n; i++){
        if (color[i] == 0){
            col++;
            dfs(i);
        }
    }
    if(bad()){
        cout << 0;
        return 0;
    }
    cout << tav(ans - 1);
}


///in his name! hi again :P :D :) nothing bad has happened yet :) :| and FYI i think i love Toktam! nice guy :)
///today is 6,8,94
#include <iostream>
#include <vector>
#include <algorithm>
#define pb push_back
#define F first
#define S second
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;

const int maxn = 1e5 + 10;
const ll mod = 1e9 + 7;
int n, m, mark[maxn], color[maxn], col = 0, ted = 0;
vector <pii> hate;
vector <int> G[maxn], Gp[maxn], Gz[maxn];
ll tav(int b){
    if (b < 0)
        return 0;
    ll ans = 1ll;
    for (int i = 0; i < b; i++){
        ans *= 2ll;
        ans %= 1ll * mod;
    }
    return ans;
}
void dfs(int u){
    color[u] = col;
    for (int i = 0; i < G[u].size(); i++)
        if (color[G[u][i]] == 0)
            dfs(G[u][i]);
    return;
}
bool dfsp(int u, int par){
    mark[u] = 1;
    int k = 0;
    for (int i = 0; i < Gp[u].size(); i++){
        if (!mark[Gp[u][i]]){
            if(dfsp(Gp[u][i], u))
                return 1;
        }
        else if (Gp[u][i] != par)
            return 1;
    }
    return 0;
}
void prep(int u){
    sort(Gz[u].begin(), Gz[u].end());
    int i = 0;
    while(i < Gz[u].size()){
        Gp[u].pb(Gz[u][i]);
        while(i + 1 < Gz[u].size() && Gz[u][i + 1] == Gz[u][i]) i++;
        i++;
    }
}
bool bad(){
    for (int i = 0; i < hate.size(); i++){
        int u = hate[i].F, v = hate[i].S;
        if (color[u] == color[v])
            return 1;
        Gz[color[u]].pb(color[v]);
        Gz[color[v]].pb(color[u]);
    }
    for (int i = 1; i <= col; i++)
        prep(i);
    for (int i = 1; i <= col; i++){
        if (!mark[i]){
            ted++;
            if (dfsp(i, -1)){
                return 1;
            }
        }
    }
    return 0;
}
int main(){
    cin >> n >> m;
    for (int i = 0; i < m; i++){
        int u, v, w;
        cin >> u >> v >> w;     u--, v--;
        if (w){ /// in love :
            G[u].pb(v), G[v].pb(u);
        }else{ /// hate :
            hate.pb(pii(u, v));
        }
    }
    for (int i = 0; i < n; i++){
        if (color[i] == 0){
            col++;
            dfs(i);
        }
    }
    if(bad()){
        cout << 0;
        return 0;
    }
    cout << tav(ted - 1);
}


///in his name! hi again :P :D :) nothing bad has happened yet :) :| and FYI i think i love Toktam! nice guy :)
///today is 6,8,94
#include <iostream>
#include <vector>
#include <algorithm>
#define pb push_back
#define F first
#define S second
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;

const int maxn = 1e5 + 10, mod = 1e9 + 7;
int n, m, mark[maxn], color[maxn], col = 0, ted = 0;
vector <pii> hate;
vector <int> G[maxn], Gp[maxn], Gz[maxn];
ll tav(int b){
    ll ans = 1ll;
    for (int i = 0; i < b; i++){
        ans *= 2ll;
        ans %= 1ll * mod;
    }
    return ans;
}
void dfs(int u){
    color[u] = col;
    for (int i = 0; i < G[u].size(); i++)
        if (!color[G[u][i]])
            dfs(G[u][i]);
    return;
}
bool dfsp(int u, int par){
    mark[u] = 1;
    int k = 0;
    for (int i = 0; i < Gp[u].size(); i++){
        if (!mark[Gp[u][i]]){
            if(dfsp(Gp[u][i], u))
                return 1;
        }
        else if (Gp[u][i] != par)
            return 1;
    }
    return 0;
}
void prep(int u){
    sort(Gz[u].begin(), Gz[u].end());
    int i = 0;
    while(i < Gz[u].size()){
        Gp[u].pb(Gz[u][i]);
        while(i + 1 < Gz[u].size() && Gz[u][i + 1] == Gz[u][i]) i++;
        i++;
    }
}
bool bad(){
    for (int i = 0; i < hate.size(); i++){
        int u = hate[i].F, v = hate[i].S;
        if (color[u] == color[v])
            return 1;
        Gz[color[u]].pb(color[v]);
        Gz[color[v]].pb(color[u]);
    }
    for (int i = 1; i <= col; i++)
        prep(i);
    for (int i = 1; i <= col; i++){
        if (!mark[i]){
            ted++;
            if (dfsp(i, -1)){
                return 1;
            }
        }
    }
    return 0;
}
int main(){
    cin >> n >> m;
    for (int i = 0; i < m; i++){
        int u, v, w;
        cin >> u >> v >> w;     u--, v--;
        if (w){ /// in love :
            G[u].pb(v), G[v].pb(u);
        }else{ /// hate :
            hate.pb(pii(u, v));
        }
    }
    for (int i = 0; i < n; i++){
        if (!color[i]){
            col++;
            dfs(i);
        }
    }
    if(bad()){
        cout << 0;
        return 0;
    }
    cout << tav(ted - 1);
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
const int sz = 100005, mod = 1000000007;
int n,m;
vector <int> gd[sz],bd[sz],bad[sz];
int gpid[sz],gp;
int clr[sz];

void dfs(int x){
    if(gpid[x]!=-1) return;
    gpid[x] = gp;
    for(int i:gd[x]){
        dfs(i);
    }
}

int dfsclr(int x,int col){
    if(clr[x]!=-1) return clr[x]==col;
    clr[x] = col;
    for(int i:bad[x]){
        if(dfsclr(i,1-col)==0) return 0;
    }
    return 1;
}

void sol()
{
    int cnt = 0;
    for(int i=0;i<gp;i++){
        if(clr[i]==-1){
            if(!dfsclr(i,1)){
                printf("0\n");
                return;
            }
            cnt++;
        }
    }
    ll ans = 1;
    cnt--;
    while(cnt){
        ans *= 2;
        ans %= mod;
        cnt--;
    }
    printf("%lld\n",ans);
}

void hi(int x){
    x++;
    return;
}
int main()
{
    int i,a,b,c;
    while(scanf("%d %d",&n,&m)!=EOF){
        for(i=0;i<m;i++){
            scanf("%d %d %d",&a,&b,&c);
            if(c!=1){
                bd[a].push_back(b);
                bd[b].push_back(a);
            }
            else{
                gd[a].push_back(b);
                gd[b].push_back(a);
            }
        }
        memset(gpid,-1,sizeof(gpid));
        gp = 0;
        for(i=1;i<=n;i++){
            hi(9);
            if(gpid[i]==-1){
                dfs(i);
                gp++;
            }
        }
        for(i=1;i<=n;i++){
            for(int j:bd[i]){
                bad[gpid[i]].push_back(gpid[j]);
            }
        }
        memset(clr,-1,sizeof(clr));
        sol();
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
const int sz = 100005, mod = 1000000007;
int n,m;
int dset[sz],vis[sz];
vector <int> gra[sz];
typedef struct A
{
    int a,b;
}AA;
AA hate[sz];
int bipart;

int findg(int x){
    if(dset[x]==-1) return x;
    else return dset[x] = findg(dset[x]);
}
void uni(int a,int b){
    int x = findg(a), y = findg(b);
    dset[x] = y;
    //num[y] += num[x];
}

void dfs(int x){
    vis[x] = 1;
    int i,y;
    for(i=0;i<gra[x].size();i++){
        y = gra[x][i];
        if(vis[y]==0) dfs(y);
    }
}

ll pow(ll a, ll b){
    ll ret = 1;
    while(b){
        if(b&1) ret *= a;
        a *= a, b /= 2;
        ret %= mod, a %= mod;
    }
    return ret;
}

void draw(int x, int cur){
    vis[x] = cur;
    int i,y;
    for(i=0;i<gra[x].size();i++){
        y = gra[x][i];
        if(vis[y]==0) draw(y,-cur);
        else if(vis[y]==cur){
            bipart = 0;
            return;
        }
        if(!bipart) return;
    }
}

int main()
{
    int i,j;
    int a,b,c,x,y;
    ll cnt;
    int flag;
    while(scanf("%d %d",&n,&m)!=EOF){
        cnt = j = flag =0;
        memset(dset,-1,sizeof(dset));
        memset(vis,0,sizeof(vis));
        for(i=0;i<m;i++){
            scanf("%d %d %d",&a,&b,&c);
            if(c!=1){
                hate[j].a = a;
                hate[j++].b = b;
            }
            else{
                uni(a,b);
            }
        }
        for(i=0;i<j;i++){
            x = findg(hate[i].a), y = findg(hate[i].b);
            gra[x].push_back(y);//, gra[y].push_back(x);
        }
        memset(vis,0,sizeof(vis));
        bipart = 1;
        for(i=1;i<=n;i++){
            if(dset[i]==-1 && vis[i]==0){
                draw(i,1);
                if(!bipart) break;
            }
        }
        if(!bipart){
            puts("0");
            continue;
        }
        memset(vis,0,sizeof(vis));
        for(i=1;i<=n;i++){
            if(dset[i]==-1 && vis[i]==0){
                cnt++;
                dfs(i);
            }
        }
        cnt = pow(2,cnt-1);
        printf("%lld\n",cnt);
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
const int sz = 100005, mod = 1000000007;
int n,m;
vector <int> gd[sz],bd[sz],bad[sz];
int gpid[sz],gp;
int clr[sz];

void dfs(int x){
    if(gpid[x]!=-1) return;
    gpid[x] = gp;
    for(int i:gd[x]){
        dfs(i);
    }
}

int dfsclr(int x,int col){
    if(clr[x]!=-1) return clr[x]==col;
    clr[x] = col;
    for(int i:bad[x]){
        if(dfsclr(i,1-col)==0) return 0;
    }
    return 1;
}

void sol()
{
    int cnt = 0;
    for(int i=0;i<gp;i++){
        if(clr[i]==-1){
            if(!dfsclr(i,1)){
                printf("0\n");
                return;
            }
            cnt++;
        }
    }
    ll ans = 1;
    cnt--;
    while(cnt){
        ans *= 2;
        ans %= mod;
        cnt--;
    }
    printf("%lld\n",ans);
}

int main()
{
    int i,a,b,c;
    while(scanf("%d %d",&n,&m)!=EOF){
        for(i=0;i<m;i++){
            scanf("%d %d %d",&a,&b,&c);
            if(c!=1){
                bd[a].push_back(b);
                bd[b].push_back(a);
            }
            else{
                gd[a].push_back(b);
                gd[b].push_back(a);
            }
        }
        memset(gpid,-1,sizeof(gpid));
        gp = 0;
        for(i=1;i<=n;i++){
            if(gpid[i]==-1){
                dfs(i);
                gp++;
            }
        }
        for(i=1;i<=n;i++){
            for(int j:bd[i]){
                bad[gpid[i]].push_back(gpid[j]);
            }
        }
        memset(clr,-1,sizeof(clr));
        sol();
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
const int sz = 100005, mod = 1000000007;
int n,m;
vector <int> gd[sz],bd[sz],bad[sz];
int gpid[sz],gp;
int clr[sz];

void dfs(int x){
    if(gpid[x]!=-1) return;
    gpid[x] = gp;
    for(int i:gd[x]){
        dfs(i);
    }
}

int dfsclr(int x,int col){
    if(clr[x]!=-1) return clr[x]==col;
    clr[x] = col;
    for(int i:bad[x]){
        if(dfsclr(i,1-col)==0) return 0;
    }
    return 1;
}

void sol()
{
    int cnt = 0;
    for(int i=0;i<gp;i++){
        if(clr[i]==-1){
            if(!dfsclr(i,1)){
                printf("0\n");
                return;
            }
            cnt++;
        }
    }
    ll ans = 1;
    cnt--;
    while(cnt){
        ans *= 2;
        ans %= mod;
        cnt--;
    }
    printf("%lld\n",ans);
}

void hi(int x){
    x++;
    return;
}
int main()
{
    int i,a,b,c;
    while(scanf("%d %d",&n,&m)!=EOF){
        for(i=0;i<m;i++){
            scanf("%d %d %d",&a,&b,&c);
            if(c!=1){
                bd[a].push_back(b);
                bd[b].push_back(a);
            }
            else{
                gd[a].push_back(b);
                gd[b].push_back(a);
            }
        }
        memset(gpid,-1,sizeof(gpid));
        gp = 0;
        for(i=1;i<=n;i++){
            hi();
            if(gpid[i]==-1){
                dfs(i);
                gp++;
            }
        }
        for(i=1;i<=n;i++){
            for(int j:bd[i]){
                bad[gpid[i]].push_back(gpid[j]);
            }
        }
        memset(clr,-1,sizeof(clr));
        sol();
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define sc( x ) scanf( "%d" , &x )
#define REP( i , n ) for( int i = 0 ; i < n ; i++ )
#define clr( t , val ) memset( t , val , sizeof(t) )

#define all(v)  v.begin() , v.end()
#define pb push_back
#define SZ( v ) ((int)(v).size())

#define mp make_pair
#define fi first
#define se second

#define test() cerr << "hola q hace" << endl;
#define DEBUG( x ) cerr <<  #x << "=" << x << endl;
#define DEBUG2( x , y ) cerr << #x << "=" << x << " " << #y << "=" << y << endl;

#define N 100000

typedef long long ll;
typedef vector< ll > vll;
typedef pair< int , int > pii;
typedef vector< int > vi;

ll MOD = 1000000007LL;
ll pow( ll a , ll b , ll c ){
    ll ans = 1;
    while( b ){
        if( b & 1 ) ans = (ans * a)%c;
        a = (a * a)%c;
        b >>= 1;
    }
    return ans;
}
vi G[ N + 5 ] , C[ N + 5 ];
int col[ N + 5 ];
bool solve;
queue< int > Q;
void bfs(){
    while( !Q.empty() ){
        int u = Q.front(); Q.pop();
        REP( i , SZ( G[ u ] ) ){
            int v = G[ u ][ i ] , w = C[ u ][ i ];
            if( col[ v ] == -1 ){
                col[ v ] = col[ u ] ^ w ^ 1;
                Q.push( v );
            }else if( col[ v ] != col[ u ] ^ w ^ 1 ){
                solve = 0;
            }
        }
    }
}
int main(){
    int n , m;
    while( sc( n ) == 1 ){
        sc( m );
        REP( i , N ) G[ i ].clear() , C[ i ].clear();
        int cnt = 0;
        clr( col , -1 );

        solve = 1;
        REP( it , m ){
            int u , v , w;
            sc( u ) , sc( v ) , sc( w );
            u -- , v -- ;
            if( u > v ) swap( u , v );
            if( u == 0 ){
                col[ v ] = w;
                Q.push( v );
                continue;
            }
            G[ u ].pb( v );
            C[ u ].pb( w );
            G[ v ].pb( u );
            C[ v ].pb( w );
        }
        bfs();
        for( int s = 1 ; s < n ; ++s ){
            if( col[ s ] != -1 ) continue;
            cnt ++;
            col[ s ] = 0;
            Q.push( s );
            bfs();
        }
        if( !solve ) puts( "0" );
        else{
            printf( "%d\n" , (int)pow( 2LL , (ll)cnt , MOD ) );
        }
    }
}


/*check if the graph is bipartite
 * */

/*prepare adjacency list,noting hate/love edges
 *now for each unvisited node,inc ct (possible to assign any color)
 do dfs and assign same color(start with 0) to friends and oppposite color to enemies,in case a node is already colored check if it follows the rule if not stop.
 ans=2*ct

 3rd method
 if i and j are friends then join i,j and i+n and j+n
 if i and j hate then join i,j+n and j,i+n

 if i and i+n are connected,
 then break,
 else ans=

 *
 *
 *
 *
 */
#include <iostream>
#include <algorithm>
#include<map>
#include<queue>
#include<utility>
#include<string>
#include<vector>
#include<stdio.h>
#include<string.h>

using namespace std;

#define REP(i,n) for(int i=0; i<n; i++)
#define FOR(i,x,y) for(int i=x; i<=y; i++)
#define MAX(a,b) a>b?a:b

typedef struct subset{int Parent;int Rank;}subset;

int find(subset sub[],int a)
{if(sub[a].Parent==a)return a;else {sub[a].Parent=find(sub,sub[a].Parent);return sub[a].Parent;}}

void Union(subset sub[],int a, int b)
{	int pa,pb;pa=find(sub,a);pb=find(sub,b);
	if(sub[pa].Rank>sub[pb].Rank)sub[pb].Parent=pa;
	else if(sub[pb].Rank>sub[pa].Rank)sub[pa].Parent=pb;
	else{sub[pb].Parent=pa;sub[pa].Rank++;}}

	vector<vector<pair<int,int> > > ed(1000005);
	int color[1000005],ct=0;
const int mod=1000000007;
int bfs(int i,int col)
{
	queue<int> q;
	q.push(i);

	color[i]=col;
	while(!q.empty())
	{
		int top=q.front();
		//cout<<top+1<<"="<<color[top]<<"\n";
			q.pop();
		REP(t,ed[top].size())
		{
			int i=ed[top][t].first;
			if(color[i]==2)
			{
				color[i]=ed[top][t].second^color[top];
				//cout<<"		"<<i+1<<"="<<color[i]<<"\n";
				q.push(i);
			}
			else{
				if(color[i]!=ed[top][t].second^color[top])
					return 0;
			}
		}

	}

	return 1;

}
int main()
{
	int n,m,a,b,c;
	cin>>n>>m;

	REP(i,m)
	{
		cin>>a>>b>>c;a--,b--;c^=1;
		ed[a].push_back(make_pair(b,c));
		ed[b].push_back(make_pair(a,c));
	}

	//REP(i,ed.size())
	//	REP(j,ed[i].size())
	//	cout<<i+1<<" "<<ed[i][j].first+1<<"\n";

	REP(i,n)
		color[i]=2;
	REP(i,n)
		if(color[i]==2)
		{ct++;
			//cout<<"*\n";
			if(!bfs(i,0))
			{cout<<"0";
				return 0;
			}
		}
	int ans=1;
	REP(i,ct-1)
		ans=ans*2%mod;

	cout<<ans;

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>

#define oo 1e9
#define pi 3.1415926536
#define all(x) x.begin(),x.end()
#define sorta(x) sort(all(x))
#define sortam(x,comp) sort(all(x),comp)
#define sortd(x) sort(x.rbegin(),x.rend())
#define sf(x) scanf("%d", &x);
#define sf2(x, y) scanf("%d %d", &x, &y);
#define sf3(x, y, z) scanf("%d %d %d", &x, &y, &z);
#define sfll(x) scanf("%I64d", &x);
#define sfll2(x, y) scanf("%I64d %I64d", &x, &y);
#define sfll3(x, y, z) scanf("%I64d %I64d %I64d", &x, &y, &z);
#define sfd(x) scanf("%f", &x);
#define pr(x) printf("%d ", x);

typedef long long ll;
using namespace std;
vector<vector<pair<int, int> > >g;
vector<int> c;
bool isb;

void go(int i, int col) {
    c[i] = col;
    for(int j = 0; j < g[i].size(); j++) {
        if(!isb || (g[i][j].second == 0 && c[g[i][j].first] == col) || (g[i][j].second == 1 && c[g[i][j].first] == !col)) {
            isb = 0;
            return;
        }

        if(c[g[i][j].first] == -1) go(g[i][j].first, g[i][j].second ? col : !col);
    }
}

ll mod = 1e9 + 7;
ll pw(ll b, ll p) {
    if(!p) return 1;
    if(p == 1) return b;
    if(p % 2) return (b*pw((b*b) % mod, (p - 1) / 2) % mod) % mod;
    return pw((b*b) % mod, p / 2) % mod;
}

int main() {
    int n, m;
    while(cin >> n >> m) {
        g.clear();
        g.resize(n);
        for(int i = 0; i < m; i++) {
            int x, y, c;
            sf3(x, y, c);
            g[x - 1].push_back({y - 1, c});
            g[y - 1].push_back({x - 1, c});
        }

        c.clear();
        c.resize(n, -1);
        isb = 1;
        int comp = 0;
        for(int i = 0; i < n; i++) {
            if(c[i] == -1) go(i, 1), comp++;
        }

        if(!isb) cout << 0 << endl;
        else cout << pw(2, comp - 1) << endl;
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int MAXN = 1001 * 1001 , MOD = 1e9 + 7;

int t2(int x)
{
    if(x==0)
        return 1 ;
    long long ans = t2(x/2);
    ans *= ans ;
    ans%=MOD;
    return (ans*(x%2==0?1:2))%MOD;
}

vector < int > adj [ MAXN ] ;

vector < pair < int ,int > > ed ;

int par [ MAXN ] = {} , sz [ MAXN ] = {} , t = 0 , mark [ MAXN ] = {}  ;

int root(int u)
{
    return (par[u]==u?u:par[u]=root(par[u]));
}

inline void merge(int x , int y)
{
    x=root(x) , y = root(y) ;
    if(x==y)
        return ;
    t--;
    if(sz[x]>sz[y])
        swap(x,y);
    par[x]=y;
    sz[y]+=x;
}

void dfs(int u)
{
    for(auto v : adj[u])
    {
        if(mark[v])
        {
            if(mark[v]==mark[u])
            {
                cout<<0;
                exit(0);
            }
            continue ;
        }
        mark[v]=3-mark[u];
        dfs(v);
    }
}

 main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
    int n , m;
    cin >> n >> m;
    t=n;
    for(int i = 1 ; i <= n ; i ++)
        par[i]=i,sz[i]=1;
    int x , y , z ;
    for(int i = 0 ; i < m ; i ++)
    {
        cin >> x >> y >> z ;
        if(z)
            merge(x,y);
        else
            ed.push_back({x,y});
    }
    if(ed.size()==0)
        return cout<<t2(t-1),0;
    fill(mark,mark+MAXN,1);
    for(auto u : ed)
    {
        x = root(u.first) , y = root(u.second);
        if(x==y)
            return cout<<0,0;
        mark[x]=0;
        mark[y]=0;
        adj[x].push_back(y);
        adj[y].push_back(x);
    }
     x = 0 ;
    for(int i = 1 ; i <= n ; i ++)
    {
        if(!mark[i])
        {
            mark[i]=1;
            dfs(i);
            x++;
        }
    }
    cout<<t2(x-1);

}


#include <bits/stdc++.h>
using namespace std;

const int MAXN = 1001 * 1001 , MOD = 1e9 + 7;

int t2(int x)
{
    if(x==0)
        return 1 ;
    long long ans = t2(x/2);
    ans *= ans ;
    ans%=MOD;
    return (ans*(x%2==0?1:2))%MOD;
}

vector < int > adj [ MAXN ] ;

vector < pair < int ,int > > ed ;

int par [ MAXN ] = {} , sz [ MAXN ] = {} , t = 0 , mark [ MAXN ] = {}  ;

int root(int u)
{
    return (par[u]==u?u:par[u]=root(par[u]));
}

inline void merge(int x , int y)
{
    x=root(x) , y = root(y) ;
    if(x==y)
        return ;
    t--;
    if(sz[x]>sz[y])
        swap(x,y);
    par[x]=y;
    sz[y]+=x;
}

void dfs(int u)
{
    for(auto v : adj[u])
    {
        if(mark[v])
        {
            if(mark[v]==mark[u])
            {
                cout<<0;
                exit(0);
            }
            continue ;
        }
        mark[v]=3-mark[u];
        dfs(v);
    }
}

 main()
{
   ios::sync_with_stdio(0);
   cin.tie(0);
    int n , m;
    cin >> n >> m;
    t=n;
    for(int i = 1 ; i <= n ; i ++)
        par[i]=i,sz[i]=1;
    int x , y , z ;
    for(int i = 0 ; i < m ; i ++)
    {
        cin >> x >> y >> z ;
        if(z)
            merge(x,y);
        else
            ed.push_back({x,y});
    }
    if(ed.size()==0)
        return cout<<t2(t-1),0;
    for(auto u : ed)
    {
        x = root(u.first) , y = root(u.second);
        if(x==y)
            return cout<<0,0;
        adj[x].push_back(y);
        adj[y].push_back(x);
    }
    x=0;
    for(int i = 1 ; i <= n ; i ++)
    {
        if(!mark[i]&&par[i]==i)
        {
            mark[i]=1;
            dfs(i);
            x++;
        }
    }
    cout<<t2(x-1);

}


#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define F first
#define S second
const int mod = 1000000007;
const int N = 1e5+3;
int rank[N],par[N],color[N],vis[N];
int find(int u)
{
    if(par[u]==u)
        return u;
    return par[u]=find(par[u]);
}
void join(int x,int y){
    x=find(x);
    y=find(y);
    if(x==y)return;
    if(::rank[x]<::rank[y])
        swap(x,y);
    par[y]=x;
    ::rank[x]+=::rank[y];
}
vector<int> a[N];
bool dfs(int x,int c){
    if(vis[x])return c==color[x];
    vis[x]=1;
    color[x]=c;
    for(int v : a[x]){
        if(!dfs(v,1-c))
            return false;
    }
    return true;
}
int main() {
    // your code goes here4n
    ios_base::sync_with_stdio(false);
    int n,m;
    cin>>n>>m;
    vector< pair<int,int> > hate;
    for(int i=0;i<n;i++){
        ::rank[i]=1;
        par[i]=i;
        vis[i]=0;
        color[i]=-1;
        a[i].clear();
    }
    while(m--){
        int x,y,z;
        cin>>x>>y>>z;
        if(z)
            join(x-1,y-1);
        else
            hate.pb(mp(x-1,y-1));
    }

    for(pair<int,int> p : hate){
        int u,v;
        // cout<<p.F<<" "<<p.S<<endl;
        u = find(p.F);
        v = find(p.S);

        a[u].pb(v);
        a[v].pb(u);
    }
    int cc = 0;
    for(int i=0;i<n;i++){
        int u = find(i);
        if(u==i && !vis[i]){
            if(dfs(i,0)){
                cc++;
            }
            else{
                cout<<0<<endl;
                return 0;
            }
        }
    }
    long long ans = 1;
    for(int i=0;i<cc-1;i++){
        ans*=2;
        if(ans>=mod)ans-=mod;
    }
    cout<<ans<<endl;
    return 0;
}