#define REP(a,b) for(int a=0; a<(b); ++a)
#define GO(a,b) for(int a=1; a<=(b); ++a)
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define FWDS(a,b,c,d) for(int a=(b); a<(c); a+=d)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define ALL(a) (a).begin(), (a).end()
#define SIZE(a) ((int)(a).size())
#define VAR(x) #x ": " << x << " "
#define FILL(x,y) memset(x,y,sizeof(x))
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define x first
#define y second
#define st first
#define nd second
#define pb push_back
#define mp make_pair
#define l(n) (n<<1)
#define r(n) ((n<<1)+1)
#define f(n) (n>>1)
#define lsb(a) (a&-a)

#include<vector>
#include<string.h>

using namespace std;
#ifndef ONLINE_JUDGE
#include<fstream>
ifstream cin("553C.in");
ofstream cout("553C.out");
#else
#include<iostream>
#endif

const int NMAX = 100000 + 69;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const int dx[] = {0,0,-1,1}; //1,1,-1,1};
const int dy[] = {-1,1,0,0}; //1,-1,1,-1};

typedef long long LL;
typedef pair<int, int> PII;
typedef long double K;
typedef pair<K, K> PKK;
typedef vector<int> VI;

int n,m,s;

int x,y,c; // read;
int bi[NMAX]; // bipartitness (even/odd)
vector<PII> G[NMAX];
int Q[NMAX<<4];

int binexp(int n, int p)
{
	int x=1;
	while(p)
	{
		if(p&1)	x=(1LL*x*n)%MOD, p--;
		n=(1LL*n*n)%MOD;
		p>>=1;
	}
	return x;
}

int main()
{
	cin>>n>>m;
	while(m--)
	{
		cin>>x>>y>>c;
		G[x].pb(mp(y,c));
		G[y].pb(mp(x,c));
	}

	FILL(bi, -1);

	GO(i,n)
	{
		if(bi[i]==-1)
		{
			int h=0, t=0;
			Q[t++]=i;
			while(h<t)
			{
				x=Q[h++];

				REP(j,G[x].size())
				{
					y=G[x][j].first;
					c=G[x][j].second;

					if(bi[y] == -1) // not matched to any poles
					{
						bi[y] = bi[x] + (c==0);
						Q[t++]=y;
					}
					else
					{
						if((bi[x]+bi[y]+(c==0)) % 2 != 0)
						{
							cout<<0;
							return 0;
						}
					}
				}
			}
			s++;
		}
	}
	cout<<binexp(2, s-1);
	return 0;
}


#define REP(a,b) for(int a=0; a<(b); ++a)
#define GO(a,b) for(int a=1; a<=(b); ++a)
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define FWDS(a,b,c,d) for(int a=(b); a<(c); a+=d)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define ALL(a) (a).begin(), (a).end()
#define SIZE(a) ((int)(a).size())
#define VAR(x) #x ": " << x << " "
#define FILL(x,y) memset(x,y,sizeof(x))
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define x first
#define y second
#define st first
#define nd second
#define pb push_back
#define mp make_pair
#define l(n) (n<<1)
#define r(n) ((n<<1)+1)
#define f(n) (n>>1)
#define lsb(a) (a&-a)

#include<vector>
#include<queue>
#include<string.h>

using namespace std;
#ifndef ONLINE_JUDGE
#include<fstream>
ifstream cin("553C.in");
ofstream cout("553C.out");
#else
#include<iostream>
#endif

const int NMAX = 100000 + 69;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const int dx[] = {0,0,-1,1}; //1,1,-1,1};
const int dy[] = {-1,1,0,0}; //1,-1,1,-1};

typedef long long LL;
typedef pair<int, int> PII;
typedef long double K;
typedef pair<K, K> PKK;
typedef vector<int> VI;

int n,m,s;

int x,y,c; // read;
int binexp(int n, int p)
{
	int x=1;
	while(p)
	{
		if(p&1)	x=(1LL*x*n)%MOD, p--;
		n=(1LL*n*n)%MOD;
		p>>=1;
	}
	return x;
}

int main()
{
	cin>>n>>m;

	vector<vector<PII> > G(n+1);
	vector<int> bi(n+1,-1);
	queue<int> Q;

	while(m--)
	{
		cin>>x>>y>>c;
		G[x].pb(mp(y,c));
		G[y].pb(mp(x,c));
	}

	GO(i,n)
	{
		if(bi[i]==-1)
		{
			bi[i]=0;
			Q.push(i);
			while(!Q.empty())
			{
				x=Q.front();

				REP(j,G[x].size())
				{
					y=G[x][j].first;
					c=G[x][j].second;

					if(bi[y] == -1) // not matched to any poles
					{
						bi[y] = bi[x] + (c==0);
						Q.push(y);
					}
					else
					{
						if((bi[x]+bi[y]+(c==0)) % 2 != 0)
						{
							cout<<0;
							return 0;
						}
					}
				}

				Q.pop();
			}
			s++;
		}
	}
	cout<<binexp(2, s-1);
	return 0;
}


#define REP(a,b) for(int a=0; a<(b); ++a)
#define GO(a,b) for(int a=1; a<=(b); ++a)
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define FWDS(a,b,c,d) for(int a=(b); a<(c); a+=d)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define ALL(a) (a).begin(), (a).end()
#define SIZE(a) ((int)(a).size())
#define VAR(x) #x ": " << x << " "
#define FILL(x,y) memset(x,y,sizeof(x))
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define x first
#define y second
#define st first
#define nd second
#define pb push_back
#define mp make_pair
#define l(n) (n<<1)
#define r(n) ((n<<1)+1)
#define f(n) (n>>1)
#define lsb(a) (a&-a)

#include<vector>
#include<string.h>

using namespace std;
#ifndef ONLINE_JUDGE
#include<fstream>
ifstream cin("553C.in");
ofstream cout("553C.out");
#else
#include<iostream>
#endif

const int NMAX = 100000 + 69;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const int dx[] = {0,0,-1,1}; //1,1,-1,1};
const int dy[] = {-1,1,0,0}; //1,-1,1,-1};

typedef long long LL;
typedef pair<int, int> PII;
typedef long double K;
typedef pair<K, K> PKK;
typedef vector<int> VI;

int n,m,s;

int x,y,c; // read;
int bi[NMAX]; // bipartitness (even/odd)
vector<PII> G[NMAX];
int Q[NMAX];

int binexp(int n, int p)
{
	int x=1;
	while(p)
	{
		if(p&1)	x=(1LL*x*n)%MOD, p--;
		n=(1LL*n*n)%MOD;
		p>>=1;
	}
	return x;
}

int main()
{
	cin>>n>>m;
	while(m--)
	{
		cin>>x>>y>>c;
		G[x].pb(mp(y,c));
		G[y].pb(mp(x,c));
	}

	FILL(bi, -1);

	GO(i,n)
	{
		if(bi[i]==-1)
		{
			bi[i]=0;
			int h=0, t=0;
			Q[t++]=i;
			while(h<t)
			{
				x=Q[h++];

				REP(j,G[x].size())
				{
					y=G[x][j].first;
					c=G[x][j].second;

					if(bi[y] == -1) // not matched to any poles
					{
						bi[y] = bi[x] + (c==0);
						Q[t++]=y;
					}
					else
					{
						if((bi[x]+bi[y]+(c==0)) % 2 != 0)
						{
							cout<<0;
							return 0;
						}
					}
				}
			}
			s++;
		}
	}
	cout<<binexp(2, s-1);
	return 0;
}


#define REP(a,b) for(int a=0; a<(b); ++a)
#define GO(a,b) for(int a=1; a<=(b); ++a)
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define FWDS(a,b,c,d) for(int a=(b); a<(c); a+=d)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define ALL(a) (a).begin(), (a).end()
#define SIZE(a) ((int)(a).size())
#define VAR(x) #x ": " << x << " "
#define FILL(x,y) memset(x,y,sizeof(x))
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define x first
#define y second
#define st first
#define nd second
#define pb push_back
#define mp make_pair
#define l(n) (n<<1)
#define r(n) ((n<<1)+1)
#define f(n) (n>>1)
#define lsb(a) (a&-a)

#include<vector>
#include<string.h>

using namespace std;
#ifndef ONLINE_JUDGE
#include<fstream>
ifstream cin("553C.in");
ofstream cout("553C.out");
#else
#include<iostream>
#endif

const int NMAX = 100000 + 69;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const int dx[] = {0,0,-1,1}; //1,1,-1,1};
const int dy[] = {-1,1,0,0}; //1,-1,1,-1};

typedef long long LL;
typedef pair<int, int> PII;
typedef long double K;
typedef pair<K, K> PKK;
typedef vector<int> VI;

int n,m,s;

int x,y,c; // read;
int bi[NMAX]; // bipartitness (even/odd)
vector<PII> G[NMAX];
int Q[NMAX<<1];

int binexp(int n, int p)
{
	int x=1;
	while(p)
	{
		if(p&1)	x=(1LL*x*n)%MOD, p--;
		n=(1LL*n*n)%MOD;
		p>>=1;
	}
	return x;
}

int main()
{
	cin>>n>>m;
	while(m--)
	{
		cin>>x>>y>>c;
		G[x].pb(mp(y,c));
		G[y].pb(mp(x,c));
	}

	FILL(bi, -1);

	GO(i,n)
	{
		if(bi[i]==-1)
		{
			int h=0, t=0;
			Q[t++]=i;
			while(h<t)
			{
				x=Q[h++];

				REP(j,G[x].size())
				{
					y=G[x][j].first;
					c=G[x][j].second;

					if(bi[y] == -1) // not matched to any poles
					{
						bi[y] = bi[x] + (c==0);
						Q[t++]=y;
					}
					else
					{
						if((bi[x]+bi[y]+(c==0)) % 2 != 0)
						{
							cout<<0;
							return 0;
						}
					}
				}
			}
			s++;
		}
	}
	cout<<binexp(2, s-1);
	return 0;
}


#define REP(a,b) for(int a=0; a<(b); ++a)
#define GO(a,b) for(int a=1; a<=(b); ++a)
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define FWDS(a,b,c,d) for(int a=(b); a<(c); a+=d)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define ALL(a) (a).begin(), (a).end()
#define SIZE(a) ((int)(a).size())
#define VAR(x) #x ": " << x << " "
#define FILL(x,y) memset(x,y,sizeof(x))
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define x first
#define y second
#define st first
#define nd second
#define pb push_back
#define mp make_pair
#define l(n) (n<<1)
#define r(n) ((n<<1)+1)
#define f(n) (n>>1)
#define lsb(a) (a&-a)

#include<vector>
#include<string.h>
#include<queue>

using namespace std;
#ifndef ONLINE_JUDGE
#include<fstream>
ifstream cin("553C.in");
ofstream cout("553C.out");
#else
#include<iostream>
#endif

const int NMAX = 100000 + 69;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const int dx[] = {0,0,-1,1}; //1,1,-1,1};
const int dy[] = {-1,1,0,0}; //1,-1,1,-1};

typedef long long LL;
typedef pair<int, int> PII;
typedef long double K;
typedef pair<K, K> PKK;
typedef vector<int> VI;

int n,m,s;

int x,y,c; // read;
int bi[NMAX]; // bipartitness (even/odd)
vector<PII> G[NMAX];
queue<int> Q;

int binexp(int n, int p)
{
	int x=1;
	while(p)
	{
		if(p&1)	x=(x*n)%MOD, p--;
		n=(n*n)%MOD;
		p>>=1;
	}
	return x;
}

int main()
{
	cin>>n>>m;
	while(m--)
	{
		cin>>x>>y>>c;
		G[x].pb(mp(y,c));
		G[y].pb(mp(x,c));
	}

	FILL(bi, -1);

	GO(i,n)
	{
		if(bi[i]==-1)
		{
			Q.push(i);
			while(!Q.empty())
			{
				x=Q.front();

				REP(j,G[x].size())
				{
					y=G[x][j].first;
					c=G[x][j].second;

					if(bi[y] == -1) // not matched to any poles
					{
						bi[y] = bi[x] + (c==0);
						Q.push(y);
					}
					else
					{
						if((bi[x]+bi[y]+(c==0)) % 2 != 0)
						{
							cout<<0;
							return 0;
						}
					}
				}
				Q.pop();
			}
			s++;
		}
	}
	cout<<binexp(2, s-1);
	return 0;
}


#define REP(a,b) for(int a=0; a<(b); ++a)
#define GO(a,b) for(int a=1; a<=(b); ++a)
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define FWDS(a,b,c,d) for(int a=(b); a<(c); a+=d)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define ALL(a) (a).begin(), (a).end()
#define SIZE(a) ((int)(a).size())
#define VAR(x) #x ": " << x << " "
#define FILL(x,y) memset(x,y,sizeof(x))
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define x first
#define y second
#define st first
#define nd second
#define pb push_back
#define mp make_pair
#define l(n) (n<<1)
#define r(n) ((n<<1)+1)
#define f(n) (n>>1)
#define lsb(a) (a&-a)

#include<vector>
#include<string.h>
#include<queue>

using namespace std;
#ifndef ONLINE_JUDGE
#include<fstream>
ifstream cin("553C.in");
ofstream cout("553C.out");
#else
#include<iostream>
#endif

const int NMAX = 100000 + 69;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const int dx[] = {0,0,-1,1}; //1,1,-1,1};
const int dy[] = {-1,1,0,0}; //1,-1,1,-1};

typedef long long LL;
typedef pair<int, int> PII;
typedef long double K;
typedef pair<K, K> PKK;
typedef vector<int> VI;

int n,m,s;

int x,y,c; // read;
int bi[NMAX]; // bipartitness (even/odd)
vector<PII> G[NMAX];
queue<int> Q;

int binexp(int n, int p)
{
	int x=1;
	while(p)
	{
		if(p&1)	x=(1LL*x*n)%MOD, p--;
		n=(1LL*n*n)%MOD;
		p>>=1;
	}
	return x;
}

int main()
{
	cin>>n>>m;
	while(m--)
	{
		cin>>x>>y>>c;
		G[x].pb(mp(y,c));
		G[y].pb(mp(x,c));
	}

	FILL(bi, -1);

	GO(i,n)
	{
		if(bi[i]==-1)
		{
			Q.push(i);
			while(!Q.empty())
			{
				x=Q.front();

				REP(j,G[x].size())
				{
					y=G[x][j].first;
					c=G[x][j].second;

					if(bi[y] == -1) // not matched to any poles
					{
						bi[y] = bi[x] + (c==0);
						Q.push(y);
					}
					else
					{
						if((bi[x]+bi[y]+(c==0)) % 2 != 0)
						{
							cout<<0;
							return 0;
						}
					}
				}
				Q.pop();
			}
			s++;
		}
	}
	cout<<binexp(2, s-1);
	return 0;
}


#define REP(a,b) for(int a=0; a<(b); ++a)
#define GO(a,b) for(int a=1; a<=(b); ++a)
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define FWDS(a,b,c,d) for(int a=(b); a<(c); a+=d)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define ALL(a) (a).begin(), (a).end()
#define SIZE(a) ((int)(a).size())
#define VAR(x) #x ": " << x << " "
#define FILL(x,y) memset(x,y,sizeof(x))
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define x first
#define y second
#define st first
#define nd second
#define pb push_back
#define mp make_pair
#define l(n) (n<<1)
#define r(n) ((n<<1)+1)
#define f(n) (n>>1)
#define lsb(a) (a&-a)

#include<vector>
#include<string.h>
#include<queue>

using namespace std;
#ifndef ONLINE_JUDGE
#include<fstream>
ifstream cin("553C.in");
ofstream cout("553C.out");
#else
#include<iostream>
#endif

const int NMAX = 100000 + 69;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const int dx[] = {0,0,-1,1}; //1,1,-1,1};
const int dy[] = {-1,1,0,0}; //1,-1,1,-1};

typedef long long LL;
typedef pair<int, int> PII;
typedef long double K;
typedef pair<K, K> PKK;
typedef vector<int> VI;

int n,m,s;

int x,y,c; // read;
int bi[NMAX]; // bipartitness (even/odd)
vector<PII> G[NMAX];
queue<int> Q;

int binexp(int n, int p)
{
	int x=1;
	while(p)
	{
		if(p&1)	x=(1LL*x*n)%MOD, p--;
		n=(1LL*n*n)%MOD;
		p>>=1;
	}
	return x;
}

int main()
{
	cin>>n>>m;
	while(m--)
	{
		cin>>x>>y>>c;
		G[x].pb(mp(y,c));
	}

	FILL(bi, -1);

	GO(i,n)
	{
		if(bi[i]==-1)
		{
			Q.push(i);
			while(!Q.empty())
			{
				x=Q.front();

				REP(j,G[x].size())
				{
					y=G[x][j].first;
					c=G[x][j].second;

					if(bi[y] == -1) // not matched to any poles
					{
						bi[y] = bi[x] + (c==0);
						Q.push(y);
					}
					else
					{
						if((bi[x]+bi[y]+(c==0)) % 2 != 0)
						{
							cout<<0;
							return 0;
						}
					}
				}
				Q.pop();
			}
			s++;
		}
	}
	cout<<binexp(2, s-1);
	return 0;
}


#include<bits/stdc++.h>
#define il inline
#define rg register
#define ldb double
#define lst long long
#define rgt register int
#define N 100050
#define qw ljl[i].to
#define MOD 1000000007
using namespace std;
const int Inf=1e9;
il int MAX(rgt x,rgt y){return x>y?x:y;}
il int MIN(rgt x,rgt y){return x<y?x:y;}
il int read()
{
	int s=0,m=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')m=1;ch=getchar();}
	while( isdigit(ch))s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return m?-s:s;
}

int n,m,Ans;
int hd[N],col[N],vis[N],cnt;
struct EDGE{int to,nxt,op;}ljl[N<<1];
il void Add(rgt p,rgt q,rgt op)
{ljl[++cnt]=(EDGE){q,hd[p],op},hd[p]=cnt;}

il int qpow(lst x,rgt y)
{
	rg lst ret=1;
	while(y)
	{
		if(y&1)ret=(ret*x)%MOD;
		x=(x*x)%MOD,y>>=1;
	}return ret;
}

void Dfs(rgt now,rgt fm,rgt C)
{
	if(col[now]!=0)
	{
		if(col[now]!=C)puts("0"),exit(0);
		return;
	}vis[now]=Ans,col[now]=C;
	for(rgt i=hd[now];i;i=ljl[i].nxt)
		if(qw!=fm)
		{
			if(ljl[i].op)Dfs(qw,now,C);
			else Dfs(qw,now,-C);
		}
}

int main()
{
	n=read(),m=read();
	for(rgt i=1,p,q,op;i<=m;++i)
	{
		p=read(),q=read(),op=read();
		Add(p,q,op),Add(q,p,op);
	}
	for(rgt i=1;i<=n;++i)
		if(!vis[i])++Ans,Dfs(i,0,1);
	printf("%d\n",qpow(2,Ans-1));
	return 0;
}


#include<bits/stdc++.h>
#define il inline
#define rg register
#define ldb double
#define lst long long
#define rgt register int
#define N 100050
#define qw ljl[i].to
#define MOD 1000000007
using namespace std;
const int Inf=1e9;
il int MAX(rgt x,rgt y){return x>y?x:y;}
il int MIN(rgt x,rgt y){return x<y?x:y;}
il int read()
{
	int s=0,m=0;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')m=1;ch=getchar();}
	while( isdigit(ch))s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return m?-s:s;
}

int n,m,Ans;
int hd[N],col[N],vis[N],cnt;
struct EDGE{int to,nxt,op;}ljl[N<<1];
il void Add(rgt p,rgt q,rgt op)
{ljl[++cnt]=(EDGE){q,hd[p],op},hd[p]=cnt;}

il int qpow(rgt x,rgt y)
{
	rgt ret=1;
	while(y)
	{
		if(y&1)ret=(ret*x)%MOD;
		x=(x*x)%MOD,y>>=1;
	}return ret;
}

void Dfs(rgt now,rgt fm,rgt C)
{
	if(col[now]!=0)
	{
		if(col[now]!=C)puts("0"),exit(0);
		return;
	}vis[now]=Ans,col[now]=C;
	for(rgt i=hd[now];i;i=ljl[i].nxt)
		if(qw!=fm)
		{
			if(ljl[i].op)Dfs(qw,now,C);
			else Dfs(qw,now,-C);
		}
}

int main()
{
	n=read(),m=read();
	for(rgt i=1,p,q,op;i<=m;++i)
	{
		p=read(),q=read(),op=read();
		Add(p,q,op),Add(q,p,op);
	}
	for(rgt i=1;i<=n;++i)
		if(!vis[i])++Ans,Dfs(i,0,1);
	printf("%d\n",qpow(2,Ans-1));
	return 0;
}


#include<bits/stdc++.h>
#define il inline
#define rg register
#define ldb double
#define lst long long
#define rgt register int
#define N 100050
#define qw ljl[i].to
#define MOD 1000000007
using namespace std;
const int Inf=1e9;
il int MAX(rgt x,rgt y){return x>y?x:y;}
il int MIN(rgt x,rgt y){return x<y?x:y;}
il int read()
{
    int s=0,m=0;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')m=1;ch=getchar();}
    while( isdigit(ch))s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
    return m?-s:s;
}

int n,m,Ans;
int hd[N],col[N],vis[N],cnt;
struct EDGE{int to,nxt,op;}ljl[N<<1];
il void Add(rgt p,rgt q,rgt op)
{ljl[++cnt]=(EDGE){q,hd[p],op},hd[p]=cnt;}

il int qpow(lst x,rgt y)
{
    rg lst ret=1;
    while(y)
    {
        if(y&1)ret=(ret*x)%MOD;
        x=(x*x)%MOD,y>>=1;
    }return ret;
}

void Dfs(rgt now,rgt fm,rgt C)
{
    if(col[now]!=0)
    {
        if(col[now]!=C)puts("0"),exit(0);
        return;
    }vis[now]=Ans,col[now]=C;
    for(rgt i=hd[now];i;i=ljl[i].nxt)
        if(qw!=fm)
        {
            if(ljl[i].op)Dfs(qw,now,C);
            else Dfs(qw,now,-C);
        }
}

int main()
{
    n=read(),m=read();
    for(rgt i=1,p,q,op;i<=m;++i)
    {
        p=read(),q=read(),op=read();
        Add(p,q,op),Add(q,p,op);
    }
    for(rgt i=1;i<=n;++i)
        if(!vis[i])++Ans,Dfs(i,0,1);
    printf("%d\n",qpow(2,Ans-1));
    return 0;
}


#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <map>
#include <algorithm>
#include <vector>
#include <stack>
#include <set>
#include <queue>
#include <iostream>

using namespace std;

#define max(a,b) ( a < b ? b : a )
#define min(a,b) ( a > b ? b : a )
#define alter(move) ( ( move + 1 ) % 2 )
#define inf -12345678
#define MAX_SIZE 100000
#define MOD 1000000007
#define T int

vector< pair<T,T> > adj[MAX_SIZE];
vector< T > graph[MAX_SIZE];
int visited[MAX_SIZE], flag;

void dfs(int start, int group)
{
	int i,temp = group;
	if( visited[ start ] != -1 ) {
		if( visited[ start ] != group ) flag = 1;
		return;
	}
	visited[ start ] = group;
	for( i=0; i<adj[start].size(); i++ ) {
		if( adj[start][i].second != 1 ) temp = ( group == 1 ? 0 : 1 );
		dfs( adj[start][i].first, temp );
	}
}

int main()
{
	T i, n, m, s1, s2, val, cnt, res;
	while( cin >> n >> m ) {

		for(i=0;i<n;i++) {
			adj[i].clear();
			graph[i].clear();
		}
		memset(visited, -1, sizeof(visited) );
		cnt = 0;
		res = 1;

		for( i=0; i<m; i++ ) {
			cin >> s1 >> s2 >> val;
			s1--;
			s2--;
			adj[s1].push_back( make_pair(s2,val) );
			adj[s2].push_back( make_pair(s1,val) );
		}

		for( i=0; i<n; i++ ) {
			if( visited[ i ] == -1) {
				flag = 0;
				dfs(i , 1);
				cnt++;
			}
			if( flag ) break;
		}
		if( flag ) {
			printf("0\n");
			continue;
		}
		for( i=0; i<cnt-1; i++ ) {
			res *= 2;
			res %= MOD;
		}
		cout<<res<<endl;
	}
	return 0;
}


#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <map>
#include <algorithm>
#include <vector>
#include <stack>
#include <set>
#include <queue>
#include <iostream>

using namespace std;

#define max(a,b) ( a < b ? b : a )
#define min(a,b) ( a > b ? b : a )
#define alter(move) ( ( move + 1 ) % 2 )
#define inf -12345678
#define MAX_SIZE 100000
#define MOD 1000000007
#define T long long

vector< pair<T,T> > adj[MAX_SIZE];
vector< T > graph[MAX_SIZE];
int visited[MAX_SIZE], flag;

void dfs(T start, int group)
{
	int i,temp;
	if( visited[ start ] != -1 ) {
		if( visited[ start ] != group ) flag = 1;
		return;
	}
	visited[ start ] = group;
	for( i=0; i<adj[start].size(); i++ ) {
		if( adj[start][i].second != 1 ) temp = ( group == 1 ? 0 : 1 );
		else temp = group;
		dfs( adj[start][i].first, temp );
	}
}

int main()
{
	T i, m, s1, s2, val, cnt, res;
	int n;
	while( cin >> n >> m ) {

		for(i=0;i<n;i++) {
			adj[i].clear();
			graph[i].clear();
		}
		memset(visited, -1, n * sizeof(int) );
		cnt = 0;
		res = 1;

		for( i=0; i<m; i++ ) {
			cin >> s1 >> s2 >> val;
			s1--;
			s2--;
			adj[s1].push_back( make_pair(s2,val) );
			adj[s2].push_back( make_pair(s1,val) );
		}

		for( i=0; i<n; i++ ) {
			if( visited[ i ] == -1) {
				flag = 0;
				dfs(i , 1);
				cnt++;
			}
			if( flag ) break;
		}
		if( flag ) {
			printf("0\n");
			continue;
		}
		for( i=0; i<cnt-1; i++ ) {
			res *= 2;
			res %= MOD;
		}
		cout<<res<<endl;
	}
	return 0;
}


#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <map>
#include <algorithm>
#include <vector>
#include <stack>
#include <set>
#include <queue>
#include <iostream>

using namespace std;

#define max(a,b) ( a < b ? b : a )
#define min(a,b) ( a > b ? b : a )
#define alter(move) ( ( move + 1 ) % 2 )
#define inf -12345678
#define MAX_SIZE 100000
#define MOD 1000000007
#define T int

vector< pair<T,T> > adj[MAX_SIZE];
vector< T > graph[MAX_SIZE];
int visited[MAX_SIZE], flag;

void dfs(int start)
{
	int i;
	for( i=0; i<adj[start].size(); i++ ) {
		if( visited[ adj[start][i].first ] == -1 ) {
			//unvisited
			visited[ adj[start][i].first ] = adj[start][i].second;
			dfs( adj[start][i].first );
		} else {
			//visited
			if( visited[ adj[start][i].first ] != adj[start][i].second  ) {
				flag = 1;
				break;
			}
		}
	}
}

int main()
{
	T i, n, m, s1, s2, val, cnt, res;
	while( cin >> n >> m ) {

		for(i=0;i<n;i++) {
			adj[i].clear();
			graph[i].clear();
		}
		memset(visited, -1, sizeof(visited) );
		cnt = 0;
		res = 1;

		for( i=0; i<m; i++ ) {
			cin >> s1 >> s2 >> val;
			s1--;
			s2--;
			if( s1 > s2 ) swap(s1,s2);
			adj[s1].push_back( make_pair(s2,val) );
		}

		flag = 0;
		for( i=0; i<n; i++ ) {
			if( visited[ i ] == -1) {
				dfs(i);
				cnt++;
			}
			if( flag ) break;
		}
		if( flag ) {
			printf("0\n");
			continue;
		}
		for( i=0; i<cnt-1; i++ ) {
			res *= 2;
			res %= MOD;
		}
		cout<<res<<endl;
	}
	return 0;
}


#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <map>
#include <algorithm>
#include <vector>
#include <stack>
#include <set>
#include <queue>
#include <iostream>

using namespace std;

#define max(a,b) ( a < b ? b : a )
#define min(a,b) ( a > b ? b : a )
#define alter(move) ( ( move + 1 ) % 2 )
#define inf -12345678
#define MAX_SIZE 100000
#define MOD 1000000007
#define T int

vector< pair<T,T> > adj[MAX_SIZE];
vector< T > graph[MAX_SIZE];
int visited[MAX_SIZE], flag, flag2;

void dfs(int start, int group)
{
	int i,temp = group;
	if( visited[ start ] != -1 ) {
		if( visited[ start ] != group ) flag = 1;
		return;
	}
	visited[ start ] = group;
	for( i=0; i<adj[start].size(); i++ ) {
		if( adj[start][i].second != 1 ) temp = ( group == 1 ? 0 : 1 );
		dfs( adj[start][i].first, temp );
	}
}

int main()
{
	T i, n, m, s1, s2, val, cnt, res;
	while( cin >> n >> m ) {

		for(i=0;i<n;i++) {
			adj[i].clear();
			graph[i].clear();
		}
		memset(visited, -1, sizeof(visited) );
		cnt = 0;
		res = 1;

		for( i=0; i<m; i++ ) {
			cin >> s1 >> s2 >> val;
			s1--;
			s2--;
			adj[s1].push_back( make_pair(s2,val) );
			adj[s2].push_back( make_pair(s1,val) );
		}

		flag = 0;
		for( i=0; i<n; i++ ) {
			if( visited[ i ] == -1) {
				dfs(i , 1);
				cnt++;
			}
			if( flag || flag2 ) break;
		}
		if( flag || flag2 ) {
			printf("0\n");
			continue;
		}
		for( i=0; i<cnt-1; i++ ) {
			res *= 2;
			res %= MOD;
		}
		cout<<res<<endl;
	}
	return 0;
}


#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <map>
#include <algorithm>
#include <vector>
#include <stack>
#include <set>
#include <queue>
#include <iostream>

using namespace std;

#define max(a,b) ( a < b ? b : a )
#define min(a,b) ( a > b ? b : a )
#define alter(move) ( ( move + 1 ) % 2 )
#define inf -12345678
#define MAX_SIZE 100000
#define MOD 1000000007
#define T long long

vector< pair<T,T> > adj[MAX_SIZE];
vector< T > graph[MAX_SIZE];
int visited[MAX_SIZE], flag;

void dfs(T start, int group)
{
	int i,temp = group;
	if( visited[ start ] != -1 ) {
		if( visited[ start ] != group ) flag = 1;
		return;
	}
	visited[ start ] = group;
	for( i=0; i<adj[start].size(); i++ ) {
		if( adj[start][i].second != 1 ) temp = ( group == 1 ? 0 : 1 );
		dfs( adj[start][i].first, temp );
	}
}

int main()
{
	T i, m, s1, s2, val, cnt, res;
	int n;
	while( cin >> n >> m ) {

		for(i=0;i<n;i++) {
			adj[i].clear();
			graph[i].clear();
		}
		memset(visited, -1, n * sizeof(int) );
		cnt = 0;
		res = 1;

		for( i=0; i<m; i++ ) {
			cin >> s1 >> s2 >> val;
			s1--;
			s2--;
			adj[s1].push_back( make_pair(s2,val) );
			adj[s2].push_back( make_pair(s1,val) );
		}

		for( i=0; i<n; i++ ) {
			if( visited[ i ] == -1) {
				flag = 0;
				dfs(i , 1);
				cnt++;
			}
			if( flag ) break;
		}
		if( flag ) {
			printf("0\n");
			continue;
		}
		for( i=0; i<cnt-1; i++ ) {
			res *= 2;
			res %= MOD;
		}
		cout<<res<<endl;
	}
	return 0;
}


#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <map>
#include <algorithm>
#include <vector>
#include <stack>
#include <set>
#include <queue>
#include <iostream>

using namespace std;

#define max(a,b) ( a < b ? b : a )
#define min(a,b) ( a > b ? b : a )
#define alter(move) ( ( move + 1 ) % 2 )
#define inf -12345678
#define MAX_SIZE 100000
#define MOD 1000000007
#define T int

vector< pair<T,T> > adj[MAX_SIZE];
vector< T > graph[MAX_SIZE];
int visited[MAX_SIZE], flag;

void dfs(int start, int group)
{
	int i,temp = group;
	if( visited[ start ] != -1 ) {
		if( visited[ start ] != group ) flag = 1;
		return;
	}
	visited[ start ] = group;
	for( i=0; i<adj[start].size(); i++ ) {
		if( adj[start][i].second != 1 ) temp = ( group == 1 ? 0 : 1 );
		dfs( adj[start][i].first, temp );
	}
}

int main()
{
	T i, n, m, s1, s2, val, cnt, res;
	while( cin >> n >> m ) {

		for(i=0;i<n;i++) {
			adj[i].clear();
			graph[i].clear();
		}
		memset(visited, -1, sizeof(visited) );
		cnt = 0;
		res = 1;

		for( i=0; i<m; i++ ) {
			cin >> s1 >> s2 >> val;
			s1--;
			s2--;
			adj[s1].push_back( make_pair(s2,val) );
			adj[s2].push_back( make_pair(s1,val) );
		}

		for( i=0; i<n; i++ ) {
			flag = 0;
			if( visited[ i ] == -1) {
				dfs(i , 1);
				cnt++;
			}
			if( flag ) break;
		}
		if( flag ) {
			printf("0\n");
			continue;
		}
		for( i=0; i<cnt-1; i++ ) {
			res *= 2;
			res %= MOD;
		}
		cout<<res<<endl;
	}
	return 0;
}


#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <map>
#include <algorithm>
#include <vector>
#include <stack>
#include <set>
#include <queue>
#include <iostream>

using namespace std;

#define max(a,b) ( a < b ? b : a )
#define min(a,b) ( a > b ? b : a )
#define alter(move) ( ( move + 1 ) % 2 )
#define inf -12345678
#define MAX_SIZE 100000
#define MOD 1000000007
#define T int

vector< pair<T,T> > adj[MAX_SIZE];
vector< T > graph[MAX_SIZE];
int visited[MAX_SIZE], flag;

void dfs(int start, int group)
{
	int i,temp = group;
	if( visited[ start ] != -1 ) {
		if( visited[ start ] != group ) flag = 1;
		return;
	}
	visited[ start ] = group;
	for( i=0; i<adj[start].size(); i++ ) {
		if( adj[start][i].second != 1 ) temp = ( group == 1 ? 0 : 1 );
		dfs( adj[start][i].first, temp );
	}
}

int main()
{
	T i, n, m, s1, s2, val, cnt, res;
	while( cin >> n >> m ) {

		for(i=0;i<n;i++) {
			adj[i].clear();
			graph[i].clear();
		}
		memset(visited, -1, n*sizeof(int) );
		cnt = 0;
		res = 1;

		for( i=0; i<m; i++ ) {
			cin >> s1 >> s2 >> val;
			s1--;
			s2--;
			adj[s1].push_back( make_pair(s2,val) );
			adj[s2].push_back( make_pair(s1,val) );
		}

		for( i=0; i<n; i++ ) {
			if( visited[ i ] == -1) {
				flag = 0;
				dfs(i , 1);
				cnt++;
			}
			if( flag ) break;
		}
		if( flag ) {
			printf("0\n");
			continue;
		}
		for( i=0; i<cnt-1; i++ ) {
			res *= 2;
			res %= MOD;
		}
		cout<<res<<endl;
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#ifdef _WIN32
#define lld I64d
#endif

#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, a, b) for (int (i) = (a); i < (b); ++(i))
#define mp make_pair
#define ll long long
#define MOD 1000000007
#define inf 100007
#define maxn 100007
#define maxm 100007

const double eps = 1e-4;
constexpr double pi = acos(-1);

ll mult_mod(ll a, ll b, ll c) {
    a %= c;
    b %= c;
    ll ret = 0;
    ll tmp = a;
    while (b) {
        if (b & 1) {
            ret += tmp;
            if (ret > c) ret -= c;
        }
        tmp <<= 1;
        if (tmp > c) tmp -= c;
        b >>= 1;
    }
    return ret;
}

ll pow_mod(ll a, ll n, ll mod) {
    ll ret = 1;
    ll temp = a % mod;
    while (n) {
        if (n & 1) ret = mult_mod(ret, temp, mod);
        temp = mult_mod(temp, temp, mod);
        n >>= 1;
    }
    return ret;
}

struct Edge {
    int v, next;
};

int f[maxn];

void init() {
    rep(i, 0, maxn)    f[i] = i;
    return;
}

int find(int c) {
    if (f[c] == c)    return c;
    return f[c] = find(f[c]);
}

struct Graph {
    int head[maxn], color[maxn];
    int tot = 1;
    Edge edge[(maxm) << 1];

    void addedge(int u, int v) {
        edge[tot].v = v;
        edge[tot].next = head[u];
        head[u] = tot++;
        return;
    }

    bool dfs(int s, int co) {
        bool re = true;
        color[s] = co;
        for (int i = head[s]; i; i = edge[i].next) {
            int v = edge[i].v;
            if (color[v] == co)    return false;
            if (color[v] == 2)    re = re && dfs(v, 1 - co);
        }
        return re;
    }

    void init(int n = maxn) {
        tot = 1;
        mem(head, 0);
        rep(i, 0, n - 1)    color[i + 1] = 2;
        return;
    }
} zero;

pair<int, int> tmp[maxm];
int ltmp = 0;

int main()
{
#ifdef DEBUG
    assert(freopen("in", "r", stdin));
#endif
    int n, m, a, b, c, f1, f2;
    scanf("%d%d", &n, &m);
    zero.init();
    init();
    rep(i, 0, m) {
        scanf("%d%d%d", &a, &b, &c);
        if (c) {
            f1 = find(a), f2 = find(b);
            if (f1 != f2)    f[f1] = f2;
        } else {
            tmp[ltmp++] = make_pair(a, b);
        }
    }
    rep(i, 0, n)    find(i + 1);
    for (int i = 0; i < ltmp; ++i) {
        pair<int, int> e = tmp[i];
        f1 = find(e.first);
        f2 = find(e.second);
        zero.addedge(f1, f2);
        zero.addedge(f2, f1);
    }

    int cnt = 0;
    rep(i, 0, n) {
        if (zero.color[f[i + 1]] == 2) {
            if (zero.dfs(f[i + 1], 0))    ++cnt;
            else {
                puts("0");
                return 0;
            }
        }
    }

    ll  ans = pow_mod(2, cnt - 1, MOD);
    printf("cnt: %I64d\n", ans);
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#ifdef _WIN32
#define lld I64d
#endif

#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, a, b) for (int (i) = (a); i < (b); ++(i))
#define mp make_pair
#define ll long long
#define MOD 1000000007
#define inf 100007
#define maxn 100007
#define maxm 100007

const double eps = 1e-4;
constexpr double pi = acos(-1);

ll mult_mod(ll a, ll b, ll c) {
    a %= c;
    b %= c;
    ll ret = 0;
    ll tmp = a;
    while (b) {
        if (b & 1) {
            ret += tmp;
            if (ret > c) ret -= c;
        }
        tmp <<= 1;
        if (tmp > c) tmp -= c;
        b >>= 1;
    }
    return ret;
}

ll pow_mod(ll a, ll n, ll mod) {
    ll ret = 1;
    ll temp = a % mod;
    while (n) {
        if (n & 1) ret = mult_mod(ret, temp, mod);
        temp = mult_mod(temp, temp, mod);
        n >>= 1;
    }
    return ret;
}

struct Edge {
    int v, next;
};

int f[maxn];

void init() {
    rep(i, 0, maxn)    f[i] = i;
    return;
}

int find(int c) {
    if (f[c] == c)    return c;
    return f[c] = find(f[c]);
}

struct Graph {
    int head[maxn], color[maxn];
    int tot = 1;
    Edge edge[(maxm) << 1];

    void addedge(int u, int v) {
        edge[tot].v = v;
        edge[tot].next = head[u];
        head[u] = tot++;
        return;
    }

    bool dfs(int s, int co) {
        bool re = true;
        color[s] = co;
        for (int i = head[s]; i; i = edge[i].next) {
            int v = edge[i].v;
            if (color[v] == co)    return false;
            if (color[v] == 2)    re = re && dfs(v, 1 - co);
        }
        return re;
    }

    void init(int n = maxn) {
        tot = 1;
        mem(head, 0);
        rep(i, 0, n - 1)    color[i + 1] = 2;
        return;
    }
} zero;

pair<int, int> tmp[maxm];
int ltmp = 0;

int main()
{
#ifdef DEBUG
    assert(freopen("in", "r", stdin));
#endif
    int n, m, a, b, c, f1, f2;
    scanf("%d%d", &n, &m);
    zero.init();
    init();
    rep(i, 0, m) {
        scanf("%d%d%d", &a, &b, &c);
        if (c) {
            f1 = find(a), f2 = find(b);
            if (f1 != f2)    f[f1] = f2;
        } else {
            tmp[ltmp++] = make_pair(a, b);
        }
    }
    rep(i, 0, n)    find(i + 1);
    for (int i = 0; i < ltmp; ++i) {
        pair<int, int> e = tmp[i];
        f1 = find(e.first);
        f2 = find(e.second);
        zero.addedge(f1, f2);
        zero.addedge(f2, f1);
    }

    int cnt = 0;
    rep(i, 0, n) {
        if (zero.color[f[i + 1]] == 2) {
            if (zero.dfs(f[i + 1], 0))    ++cnt;
            else {
                puts("0");
                return 0;
            }
        }
    }

    ll  ans = pow_mod(2, cnt - 1, MOD);
    printf("%I64d\n", ans);
    return 0;
}


#include <bits/stdc++.h>

namespace fastinput
{
    /** Interface */

    inline int readChar();
    template <class T = int> inline T readInt();
    template <class T> inline void writeInt(T x, char end = 0);
    inline void writeChar(int x);
    inline void writeWord(const char *s);

    /** Read */

    static const int buf_size = 16384;

    inline int getChar() {
    	static char buf[buf_size];
    	static int len = 0, pos = 0;
    	if (pos == len)
    		pos = 0, len = fread(buf, 1, buf_size, stdin);
    	if (pos == len)
    		return -1;
    	return buf[pos++];
    }

    inline int readChar() {
    	int c = getChar();
    	while (c <= 32)
    		c = getChar();
    	return c;
    }

    template <class T>
    inline T readInt() {
    	int s = 1, c = readChar();
    	T x = 0;
    	if (c == '-')
    		s = -1, c = getChar();
    	while ('0' <= c && c <= '9')
    		x = x * 10 + c - '0', c = getChar();
    	return s == 1 ? x : -x;
    }

    /** Write */

    static int write_pos = 0;
    static char write_buf[buf_size];

    inline void writeChar(int x) {
    	if (write_pos == buf_size)
    		fwrite(write_buf, 1, buf_size, stdout), write_pos = 0;
    	write_buf[write_pos++] = x;
    }

    template <class T>
    inline void writeInt(T x, char end) {
    	if (x < 0)
    		writeChar('-'), x = -x;

    	char s[24];
    	int n = 0;
    	while (x || !n)
    		s[n++] = (char)('0' + x % 10), x /= 10;
    	while (n--)
    		writeChar(s[n]);
    	if (end)
    		writeChar(end);
    }

    inline void writeWord(const char *s) {
    	while (*s)
    		writeChar(*s++);
    }

    struct Flusher {
    	~Flusher() {
    		if (write_pos)
    			fwrite(write_buf, 1, write_pos, stdout), write_pos = 0;
    	}
    } flusher;
}

using namespace std;
using namespace fastinput;

#ifdef _WIN32
#define lld I64d
#endif

#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, a, b) for (int (i) = (a); i < (b); ++(i))
#define mp make_pair
#define ll long long
#define MOD 1000000007

const double eps = 1e-4;
constexpr double pi = acos(-1);
constexpr int maxn = 100000 + 7;
constexpr int maxm = 100000 + 7;

struct Edge {
    int v, w, next;
};

int sp[maxn];
struct Graph {
    int head[maxn], vis[maxn], color[maxn];
    int tot = 1;
    Edge edge[maxm << 1];

    void addedge(int u, int v, int w) {
        edge[tot].v = v;
        edge[tot].w = w;
        edge[tot].next = head[u];
        head[u] = tot++;
        return;
    }

    bool dfs(int s, int col) {
        vis[s] = true;
        color[s] = col;
        bool t = true;
        for (int i = head[s]; i; i = edge[i].next) {
            int v = edge[i].v;
            if (sp[s] == sp[v])    t = false;
            else if (!vis[v])    t = dfs(v, 1 - col);
            else if (color[s] == color[v])    t = false;
            if (!t)    return false;
        }
        return t;
    }

    void print(int n = maxn) {
        for (int i = 1; i <= n; ++i) {
            cout << i << " :";
            for (int j = head[i]; j; j = edge[j].next)
                cout << ' ' << edge[j].v;

            cout << endl;
        }
        return;
    }

    void init(int n = maxn) {
        tot = 1;
        mem(head, 0);
        mem(color, -1);
        mem(vis, false);
        return;
    }
};

ll mult_mod(ll a, ll b, ll c) {
    a %= c;
    b %= c;
    ll ret = 0;
    ll tmp = a;
    while (b) {
        if (b & 1) {
            ret += tmp;
            if (ret > c) ret -= c;
        }
        tmp <<= 1;
        if (tmp > c)    tmp -= c;
        b >>= 1;
    }
    return ret;
}

ll pow_mod(ll a, ll n, ll mod) {
    ll ret = 1;
    ll temp = a % mod;
    while (n) {
        if (n & 1)    ret = mult_mod(ret, temp, mod);
        temp = mult_mod(temp, temp, mod);
        n >>= 1;
    }
    return ret;
}

Graph g;

int find(int i) {
    if (sp[i] == i)    return i;
    else     return sp[i] = find(sp[i]);
}

int main()
{
#ifdef DEBUG
    assert(freopen("in", "r", stdin));
#endif
    int n, m, a, b, c;
    n = readInt();
    m = readInt();

    g.init();
    for (int i = 1; i <= n; ++i)    sp[i] = i;

    for (int i = 0; i < m; ++i) {
        a = readInt();
        b = readInt();
        c = readInt();
 //       cout << a << ' ' << b << ' ' << c << endl;
        if (c) {
            int pa = find(a), pb = find(b);
            if (pa != pb)     sp[pa] = pb;
        } else {
            g.addedge(a, b, 0);
            g.addedge(b, a, 0);
        }
    }
//    cout << endl;

    /*
    g.print(n);
    cout << endl;
*/
    for (int i = 1; i <= n; ++i)     sp[i] = find(i);

    /*
    for (int j = 1; j <= n; ++j)
        cout << sp[j] << ' ';
    cout << endl;
*/
    ll cnt = 0;
    bool f = true;
    for (int i = 1; i <= n; ++i)
        if (!g.vis[sp[i]]) {
//            cout << ':' << i << endl;
            f = f && g.dfs(sp[i], 0);
            cnt++;
        }

    if (!f) {
        puts("0");
        return 0;
    }
    ll ans = pow_mod(2, cnt - 1, MOD);
    printf("%lld\n", ans);
    return 0;
}


#include <bits/stdc++.h>
#define pii pair<int, int>
#define p first
#define s second
#define MOD 1000000007
#define MAX 111111

using namespace std;

pii P[MAX];

pii find(int x)
{
    if (P[x].p != x)
    {
        int s = P[x].s;
        P[x] = find(P[x].p);
        P[x].s = (P[x].s + s) % 2;
    }
    return P[x];
}

int comps;

bool Union(int x, int y, int t)
{
    pii px = find(x), py = find(y);
    if (px.p != py.p)
    {
        P[py.p] = {px.p, (px.s + t - py.s + 2) % 2};
        comps--;
        return true;
    }
    if ((px.s + t) % 2 != py.s)
        return false;
    return true;
}

int main()
{
    int N, M;
    cin >> N >> M;
    comps = N;
    for (int i = 1; i <= N; i++) P[i] = {i, 0};
    int u, v, t;
    for (int i = 0; i < M; i++)
    {
        scanf("%d %d %d", &u, &v, &t);
        if (not Union(u, v, 1 - t))
        {
            cout << "0\n";
            return 0;
        }
    }

    int ans = 1;
    for (int i = 1; i < comps; i++)
        ans = (ans * 2) % MOD;
    cout << ans << endl;
}


#include <bits/stdc++.h>
#define pii pair<int, int>
#define p first
#define s second
#define MOD 1000000007
#define MAX 111111

using namespace std;

pii P[MAX];

pii find(int x)
{
    if (P[x].p != x)
    {
        int s = P[x].s;
        P[x] = find(P[x].p);
        P[x].s = (P[x].s + s) % 2;
    }
    return P[x];
}

int comps;

bool Union(int x, int y, int t)
{
    pii px = find(x), py = find(y);
    if (px != py)
    {
        P[py.p] = {px.p, (px.s + t) % 2};
        comps--;
        return true;
    }
    if ((px.p + t) % 2 != py.p % 2)
        return false;
    return true;
}

int main()
{
    int N, M;
    cin >> N >> M;
    comps = N;
    for (int i = 1; i <= N; i++) P[i] = {i, 0};
    int u, v, t;
    while (M--)
    {
        scanf("%d %d %d", &u, &v, &t);
        if (not Union(u, v, t))
        {
            cout << "0\n";
            return 0;
        }
    }

    int ans = 1;
    for (int i = 1; i < comps; i++)
        ans = (ans * 2) % MOD;
    cout << ans << endl;
}


#include <bits/stdc++.h>
#define pii pair<int, int>
#define p first
#define s second
#define MOD 1000000007
#define MAX 111111

using namespace std;

pii P[MAX];

pii find(int x)
{
    if (P[x].p != x)
    {
        int s = P[x].s;
        P[x] = find(P[x].p);
        P[x].s = (P[x].s + s) % 2;
    }
    return P[x];
}

int comps;

bool Union(int x, int y, int t)
{
    pii px = find(x), py = find(y);
    if (px != py)
    {
        P[py.p] = {px.p, (px.s + t - py.s + 2) % 2};
        comps--;
        return true;
    }
    if ((px.s + t) % 2 != py.s)
        return false;
    return true;
}

int main()
{
    int N, M;
    cin >> N >> M;
    comps = N;
    for (int i = 1; i <= N; i++) P[i] = {i, 0};
    int u, v, t;
    for (int i = 0; i < M; i++)
    {
        scanf("%d %d %d", &u, &v, &t);
        if (not Union(u, v, 1 - t))
        {
            cout << "0\n";
            return 0;
        }
    }

    int ans = 1;
    for (int i = 1; i < comps; i++)
        ans = (ans * 2) % MOD;
    cout << ans << endl;
}


#include <bits/stdc++.h>
#define pii pair<int, int>
#define p first
#define s second
#define MOD 1000000007
#define MAX 111111

using namespace std;

pii P[MAX];

pii find(int x)
{
    if (P[x].p != x)
    {
        int s = P[x].s;
        P[x] = find(P[x].p);
        P[x].s = (P[x].s + s) % 2;
    }
    return P[x];
}

int comps;

bool Union(int x, int y, int t)
{
    pii px = find(x), py = find(y);
    if (px != py)
    {
        P[py.p] = {px.p, (px.s + t - py.s + 4) % 2};
        comps--;
        return true;
    }
    if ((px.s + t) % 2 != py.s % 2)
        return false;
    return true;
}

int main()
{
    int N, M;
    cin >> N >> M;
    comps = N;
    for (int i = 1; i <= N; i++) P[i] = {i, 0};
    int u, v, t;
    while (M--)
    {
        scanf("%d %d %d", &u, &v, &t);
        if (not Union(u, v, t))
        {
            cout << "0\n";
            return 0;
        }
    }

    int ans = 1;
    for (int i = 1; i < comps; i++)
        ans = (ans * 2) % MOD;
    cout << ans << endl;
}


///Be name Khoda

#include<bits/stdc++.h>

using namespace std;

#define ld long double
#define pb push_back
#define F first
#define S second
#define TL ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
//#define int long long int

const int N=1e5+100;

int n,m;
vector <int> love[N],hate[N];
int p=0;
int id_love[N];
bool mark[N];

void dfs_love(int v){
    mark[v]=1;
    id_love[v]=p;
    for(int u : love[v]){
        if(!mark[u]){
            dfs_love(u);
        }
    }
}

bool check_hate(int v){
    for(int u : hate[v]){
        if(id_love[u]==id_love[v]){
            return 0;
        }
    }
    return 1;
}
vector <int> hc[N];
int p2=0;
void dfs_hate(int v){
    mark[v]=1;
    for(int u : hc[v]){
        if(!mark[u]){
            dfs_hate(u);
        }
    }
}
int ans=-1;
long long int javab=1;
const int Mod=1e9+7;
int root;
int baba[N];
bool vis[N];
bool b=0;

void check_t(int v){
    mark[v]=1;
    vis[v]=1;
    for(int u : hate[v]){
        if(!vis[u]){
            baba[u]=v;
            if(v!=root){
                vis[baba[v]]=0;
            }
            if(mark[u]){
                b=1;
            }
            check_t(u);
            if(v!=root){
                vis[baba[v]]=1;
            }
        }
    }
}

int32_t main(){
    TL
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        x--;
        y--;
        if(z){
            love[x].pb(y);
            love[y].pb(x);
        }
        else{
            hate[x].pb(y);
            hate[y].pb(x);
        }
    }
    for(int i=0;i<n;i++){
        if(!mark[i]){
            dfs_love(i);
            p++;
        }
    }
    fill_n(mark,n,0);
    for(int i=0;i<n;i++){
        if(!check_hate(i)){
            cout<<0;
            return 0;
        }
    }
    for(int i=0;i<n;i++){
        if(!mark[i]){
            root=i;
            check_t(i);
            if(b){
                cout<<0;
                return 0;
            }
        }
    }
    fill_n(mark,n,0);
    for(int i=0;i<n;i++){
        for(int u : hate[i]){
            hc[id_love[u]].pb(id_love[i]);
        }
    }
    for(int i=0;i<p;i++){
        if(!mark[i]){
            dfs_hate(i);
            ans++;
        }
    }
    for(int i=0;i<ans;i++){
        javab*=(long long)2;
        javab%=(long long)Mod;
    }
    cout<<javab;
}


///Be name Khoda

#include<bits/stdc++.h>

using namespace std;

#define ld long double
#define pb push_back
#define F first
#define S second
#define TL ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

const int N=1e5+100;
const int Mod=1000*1000*1000+7;

int n,m;
vector <int> love[N],hate[N];
int p=0;
int id_love[N];
bool mark[N];
vector <int> hc[N];
int p2=0;
int ans=-1;
long long int javab=1;
int root;
int baba[N];
bool b=0;

void dfs_love(int v){
    mark[v]=1;
    id_love[v]=p;
    for(int u : love[v]){
        if(!mark[u]){
            dfs_love(u);
        }
    }
}
bool check_hate(int v){
    for(int u : hate[v]){
        if(id_love[u]==id_love[v]){
            return 0;
        }
    }
    return 1;
}

void dfs_hate(int v){
    mark[v]=1;
    for(int u : hc[v]){
        if(!mark[u]){
            dfs_hate(u);
        }
    }
}

void check_t(int v){
    mark[v]=1;
    for(int u : hate[v]){
        if(!mark[u]){
            baba[u]=v;
            if(v!=root){
                for(int l : hate[u]){
                    if(l==baba[v]){
                        b=1;
                    }
                }
            }
            check_t(u);
        }
    }
}

int32_t main(){
    TL
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        x--;
        y--;
        if(z){
            love[x].pb(y);
            love[y].pb(x);
        }
        else{
            hate[x].pb(y);
            hate[y].pb(x);
        }
    }
    for(int i=0;i<n;i++){
        if(!mark[i]){
            dfs_love(i);
            p++;
        }
    }
    fill_n(mark,n,0);
    for(int i=0;i<n;i++){
        if(!check_hate(i)){
            cout<<0;
            return 0;
        }
    }
    for(int i=0;i<n;i++){
        if(!mark[i]){
            root=i;
            check_t(i);
            if(b){
                cout<<0;
                return 0;
            }
        }
    }
    fill_n(mark,n,0);
    for(int i=0;i<n;i++){
        for(int u : hate[i]){
            hc[id_love[u]].pb(id_love[i]);
        }
    }
    for(int i=0;i<p;i++){
        if(!mark[i]){
            dfs_hate(i);
            ans++;
        }
    }
    for(int i=0;i<ans;i++){
        javab*=(long long)2;
        javab%=(long long)Mod;
    }
    cout<<javab;
}


///Be name Khoda

#include<bits/stdc++.h>

using namespace std;

#define ld long double
#define pb push_back
#define F first
#define S second
#define TL ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

const int N=1e5+100;
const int Mod=1000*1000*1000+7;

int n,m;
vector <int> love[N],hate[N];
int p=0;
int id_love[N];
bool mark[N];
vector <int> hc[N];
int p2=0;
int ans=-1;
long long int javab=1;
int root;
int baba[N];
bool b=0;

void dfs_love(int v){
    mark[v]=1;
    id_love[v]=p;
    for(int u : love[v]){
        if(!mark[u]){
            dfs_love(u);
        }
    }
}
bool check_hate(int v){
    for(int u : hate[v]){
        if(id_love[u]==id_love[v]){
            return 0;
        }
    }
    return 1;
}

void dfs_hate(int v){
    mark[v]=1;
    for(int u : hc[v]){
        if(!mark[u]){
            dfs_hate(u);
        }
    }
}
int color[N];

bool check_bipartite(int v,int c){
    mark[v]=1;
    color[v]=c;
    bool mini=1;
    if(c==1){
        c=2;
    }
    else{
        c=1;
    }

    for(int u : hc[v]){
        //cout<<"*";
        if(mark[u]){
            if(color[u]==color[v]){
                //cout<<endl<<color[u];
                return 0;
            }
        }
        if(!mark[u]){
            if(!check_bipartite(u,c)){
                return 0;
            }
        }
    }
    return 1;
}

void check_t(int v){
    mark[v]=1;
    for(int u : hate[v]){
        if(!mark[u]){
            baba[u]=v;
            if(v!=root){
                for(int l : hate[u]){
                    if(l==baba[v]){
                        b=1;
                    }
                }
            }
            check_t(u);
        }
    }
}

int32_t main(){
    TL
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        x--;
        y--;
        if(z){
            love[x].pb(y);
            love[y].pb(x);
        }
        else{
            hate[x].pb(y);
            hate[y].pb(x);
        }
    }
    for(int i=0;i<n;i++){
        if(!mark[i]){
            dfs_love(i);
            p++;
        }
    }
    fill_n(mark,n,0);
    for(int i=0;i<n;i++){
        if(!check_hate(i)){
            cout<<0;
            return 0;
        }
    }
    for(int i=0;i<n;i++){
        if(!mark[i]){
            root=i;
            check_t(i);
            if(b){
                cout<<0;
                return 0;
            }
        }
    }
    fill_n(mark,n,0);
    for(int i=0;i<n;i++){
        for(int u : hate[i]){
            hc[id_love[u]].pb(id_love[i]);
        }
    }
    for(int i=0;i<p;i++){
        if(!mark[i]){
            if(!check_bipartite(i,1)){
                cout<<0;
                return 0;
            }
        }
    }
    fill_n(mark,n,0);
    for(int i=0;i<p;i++){
        if(!mark[i]){
            dfs_hate(i);
            ans++;
        }
    }
    for(int i=0;i<ans;i++){
        javab*=(long long)2;
        javab%=(long long)Mod;
    }
    cout<<javab;
}


///Be name Khoda

#include<bits/stdc++.h>

using namespace std;

#define ld long double
#define pb push_back
#define F first
#define S second
#define TL ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long int

const int N=1e5+100;

int n,m;
vector <int> love[N],hate[N];
int p=0;
int id_love[N];
bool mark[N];

void dfs_love(int v){
    mark[v]=1;
    id_love[v]=p;
    for(int u : love[v]){
        if(!mark[u]){
            dfs_love(u);
        }
    }
}

bool check_hate(int v){
    for(int u : hate[v]){
        if(id_love[u]==id_love[v]){
            return 0;
        }
    }
    return 1;
}
vector <int> hc[N];
int p2=0;
void dfs_hate(int v){
    mark[v]=1;
    for(int u : hc[v]){
        if(!mark[u]){
            dfs_hate(u);
        }
    }
}
int ans=-1;
int javab=1;
const int Mod=1e9+7;
int root;
int baba[N];
bool vis[N];
bool b=0;

void check_t(int v){
    mark[v]=1;
    vis[v]=1;
    for(int u : hate[v]){
        if(!vis[u]){
            baba[u]=v;
            if(v!=root){
                vis[baba[v]]=0;
            }
            if(mark[u]){
                b=1;
            }
            check_t(u);
            if(v!=root){
                vis[baba[v]]=1;
            }
        }
    }
}

int32_t main(){
    TL
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        x--;
        y--;
        if(z){
            love[x].pb(y);
            love[y].pb(x);
        }
        else{
            hate[x].pb(y);
            hate[y].pb(x);
        }
    }
    for(int i=0;i<n;i++){
        if(!mark[i]){
            dfs_love(i);
            p++;
        }
    }
    fill_n(mark,n,0);
    for(int i=0;i<n;i++){
        if(!check_hate(i)){
            cout<<0;
            return 0;
        }
    }
    for(int i=0;i<n;i++){
        if(!mark[i]){
            root=i;
            check_t(i);
            if(b){
                cout<<0;
                return 0;
            }
        }
    }
    fill_n(mark,n,0);
    for(int i=0;i<n;i++){
        for(int u : hate[i]){
            hc[id_love[u]].pb(id_love[i]);
            hc[id_love[i]].pb(id_love[u]);
        }
    }
    for(int i=0;i<p;i++){
        if(!mark[i]){
            dfs_hate(i);
            ans++;
        }
    }
    for(int i=0;i<ans;i++){
        javab*=2;
        javab%=Mod;
    }
    cout<<javab;
}


///Be name Khoda

#include<bits/stdc++.h>

using namespace std;

#define ld long double
#define pb push_back
#define F first
#define S second
#define TL ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long int

const int N=1e5+100;

int n,m;
vector <int> love[N],hate[N];
int p=0;
int id_love[N];
bool mark[N];

void dfs_love(int v){
    mark[v]=1;
    id_love[v]=p;
    for(int u : love[v]){
        if(!mark[u]){
            dfs_love(u);
        }
    }
}

bool check_hate(int v){
    for(int u : hate[v]){
        if(id_love[u]==id_love[v]){
            return 0;
        }
    }
    return 1;
}
vector <int> hc[N];
int p2=0;
void dfs_hate(int v){
    mark[v]=1;
    for(int u : hc[v]){
        if(!mark[u]){
            dfs_hate(u);
        }
    }
}
int ans=-1;
int javab=1;
const int Mod=1e9+7;

int32_t main(){
    TL
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        x--;
        y--;
        if(z){
            love[x].pb(y);
            love[y].pb(x);
        }
        else{
            hate[x].pb(y);
            hate[y].pb(x);
        }
    }
    for(int i=0;i<n;i++){
        if(!mark[i]){
            dfs_love(i);
            p++;
        }
    }
    fill_n(mark,n,0);
    for(int i=0;i<n;i++){
        if(!check_hate(i)){
            cout<<0;
            return 0;
        }
    }
    for(int i=0;i<n;i++){
        for(int u : hate[i]){
            hc[id_love[u]].pb(id_love[i]);
            hc[id_love[i]].pb(id_love[u]);
        }
    }
    for(int i=0;i<p;i++){
        if(!mark[i]){
            dfs_hate(i);
            ans++;
        }
    }
    for(int i=0;i<ans;i++){
        javab*=2;
        javab%=Mod;
    }
    cout<<javab;
}


///Be name Khoda

#include<bits/stdc++.h>

using namespace std;

#define ld long double
#define pb push_back
#define F first
#define S second
#define TL ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long int

const int N=1e5+100;

int n,m;
vector <int> love[N],hate[N];
int p=0;
int id_love[N];
bool mark[N];

void dfs_love(int v){
    mark[v]=1;
    id_love[v]=p;
    for(int u : love[v]){
        if(!mark[u]){
            dfs_love(u);
        }
    }
}

bool check_hate(int v){
    for(int u : hate[v]){
        if(id_love[u]==id_love[v]){
            return 0;
        }
    }
    return 1;
}
vector <int> hc[N];
int p2=0;
void dfs_hate(int v){
    mark[v]=1;
    for(int u : hc[v]){
        if(!mark[u]){
            dfs_hate(u);
        }
    }
}
int ans=-1;
int javab=1;
const int Mod=1e9+7;
int root;
int baba[N];
bool vis[N];
bool b=0;

void check_t(int v){
    mark[v]=1;
    vis[v]=1;
    for(int u : hate[v]){
        if(!vis[u]){
            baba[u]=v;
            if(v!=root){
                vis[baba[v]]=0;
            }
            if(mark[u]){
                b=1;
            }
            check_t(u);
        }
    }
}

int32_t main(){
    TL
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        x--;
        y--;
        if(z){
            love[x].pb(y);
            love[y].pb(x);
        }
        else{
            hate[x].pb(y);
            hate[y].pb(x);
        }
    }
    for(int i=0;i<n;i++){
        if(!mark[i]){
            dfs_love(i);
            p++;
        }
    }
    fill_n(mark,n,0);
    for(int i=0;i<n;i++){
        if(!check_hate(i)){
            cout<<0;
            return 0;
        }
    }
    for(int i=0;i<n;i++){
        if(!mark[i]){
            root=i;
            check_t(i);
            if(b){
                cout<<0;
                return 0;
            }
        }
    }
    fill_n(mark,n,0);
    for(int i=0;i<n;i++){
        for(int u : hate[i]){
            hc[id_love[u]].pb(id_love[i]);
            hc[id_love[i]].pb(id_love[u]);
        }
    }
    for(int i=0;i<p;i++){
        if(!mark[i]){
            dfs_hate(i);
            ans++;
        }
    }
    for(int i=0;i<ans;i++){
        javab*=2;
        javab%=Mod;
    }
    cout<<javab;
}


#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
typedef long long LL;
const LL mods=1000000007LL;
const int MAXN=100000;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
int nodes,edge,ranks[MAXN+5],par[MAXN+5],musuh[MAXN+5];
vector <pii> edgelist[5];
LL ans=0;
bool adaans=true,sudah[MAXN+5];
LL modulo(LL angka){
	if(angka>=mods)
		angka%=mods;
	return angka;
}
int finds(int u){
	if(par[u]!=u)
		par[u]=finds(par[u]);
	return par[u];
}
bool connected(int u,int v){
	return (finds(u)==finds(v));
}
void gabung(int titik1,int titik2){
	int u=finds(titik1);
	int v=finds(titik2);
	if(u==v)
		return;
	if(ranks[u]==ranks[v])
		ranks[u]++;
	if(ranks[u]>ranks[v])
	{
		par[v]=u;
		if(musuh[u]==-1)
			musuh[u]=musuh[v];
	}
	else
	{
		par[u]=v;
		if(musuh[v]==-1)
			musuh[v]=musuh[u];
	}
}
int main()
{
	memset(musuh,-1,sizeof(musuh));
	memset(sudah,false,sizeof(sudah));
	adaans=true;
	cin>>nodes>>edge;
	for(int i=1;i<=nodes;i++)
	{
		ranks[i]=0;
		par[i]=i;
	}
	for(int i=1;i<=edge;i++)
	{
		int u,v,weight;
		cin>>u>>v>>weight;
		edgelist[weight].pb(mp(u,v));
	}
	for(auto edgebaru:edgelist[1])
		gabung(edgebaru.fi,edgebaru.se);
	for(auto edgebaru:edgelist[0])
	{
		if(connected(edgebaru.fi,edgebaru.se))
		{
			adaans=false;
			break;
		}
		int u=edgebaru.fi;
		int v=edgebaru.se;
		for(int ulang=1;ulang<=2;ulang++)
		{
			if(musuh[finds(u)]==-1)
				musuh[finds(u)]=finds(v);
			else
			{
				gabung(musuh[finds(u)],v);
			}
			swap(u,v);
		}
		assert(connected(musuh[finds(u)],v));
		assert(connected(musuh[finds(v)],u));
	}
	if(!adaans)
	{
		printf("0\n");
		return 0;
	}
	for(int i=1;i<=nodes;i++)
	{
		int now=finds(i);
		if(sudah[now]||sudah[finds(musuh[now])])
			continue;
		sudah[now]=true;
		if(musuh[now]!=-1)
		{
			sudah[finds(musuh[now])]=true;
		}
		if(ans==0)
			ans=1;
		else
			ans=modulo(ans*2LL);
	}
	cout<<ans<<endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
typedef long long LL;
const LL mods=1000000007LL;
const int MAXN=100000;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
int nodes,edge,ranks[MAXN+5],par[MAXN+5],musuh[MAXN+5];
vector <pii> edgelist[5];
LL ans=0;
bool adaans=true,sudah[MAXN+5];
LL modulo(LL angka){
	if(angka>=mods)
		angka%=mods;
	return angka;
}
int finds(int u){
	if(par[u]!=u)
		par[u]=finds(par[u]);
	return par[u];
}
bool connected(int u,int v){
	return (finds(u)==finds(v));
}
void gabung(int titik1,int titik2){
	int u=finds(titik1);
	int v=finds(titik2);
	if(u==v)
		return;
	if(ranks[u]==ranks[v])
		ranks[u]++;
	int tempu=musuh[u],tempv=musuh[v];
	if(ranks[u]>ranks[v])
	{
		par[v]=u;
		if(musuh[u]==-1)
			musuh[u]=musuh[v];
	}
	else
	{
		par[u]=v;
		if(musuh[v]==-1)
			musuh[v]=musuh[u];
	}
	if(tempu!=-1&&tempv!=-1)
	{
		if(!connected(tempu,tempv))
			gabung(tempu,tempv);
	}
}
int main()
{
	memset(musuh,-1,sizeof(musuh));
	memset(sudah,false,sizeof(sudah));
	adaans=true;
	cin>>nodes>>edge;
	for(int i=1;i<=nodes;i++)
	{
		ranks[i]=0;
		par[i]=i;
	}
	for(int i=1;i<=edge;i++)
	{
		int u,v,weight;
		cin>>u>>v>>weight;
		edgelist[weight].pb(mp(u,v));
	}
	for(auto edgebaru:edgelist[1])
		gabung(edgebaru.fi,edgebaru.se);
	for(auto edgebaru:edgelist[0])
	{
		if(connected(edgebaru.fi,edgebaru.se))
		{
			adaans=false;
			break;
		}
		int u=edgebaru.fi;
		int v=edgebaru.se;
		for(int ulang=1;ulang<=2;ulang++)
		{
			if(musuh[finds(u)]==-1)
				musuh[finds(u)]=finds(v);
			gabung(musuh[finds(u)],v);
			swap(u,v);
		}
		assert(connected(musuh[finds(u)],v));
		assert(connected(musuh[finds(v)],u));
	}
	if(!adaans)
	{
		printf("0\n");
		return 0;
	}
	for(int i=1;i<=nodes;i++)
	{
		int now=finds(i);
		if(sudah[now]||sudah[finds(musuh[now])])
			continue;
		sudah[now]=true;
		if(musuh[now]!=-1)
		{
			sudah[finds(musuh[now])]=true;
		}
		if(ans==0)
			ans=1;
		else
			ans=modulo(ans*2LL);
	}
	cout<<ans<<endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
typedef long long LL;
const LL mods=1000000007LL;
const int MAXN=100000;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
int nodes,edge,ranks[MAXN+5],par[MAXN+5],musuh[MAXN+5];
vector <pii> edgelist[5];
LL ans=0;
bool adaans=true,sudah[MAXN+5];
LL modulo(LL angka){
	if(angka>=mods)
		angka%=mods;
	return angka;
}
int finds(int u){
	if(par[u]!=u)
		par[u]=finds(par[u]);
	return par[u];
}
bool connected(int u,int v){
	return (finds(u)==finds(v));
}
void gabung(int titik1,int titik2){
	int u=finds(titik1);
	int v=finds(titik2);
	if(u==v)
		return;
	if(ranks[u]==ranks[v])
		ranks[u]++;
	if(ranks[u]>ranks[v])
	{
		par[v]=u;
		if(musuh[u]==-1)
			musuh[u]=musuh[v];
	}
	else
	{
		par[u]=v;
		if(musuh[v]==-1)
			musuh[v]=musuh[u];
	}
}
int main()
{
	memset(musuh,-1,sizeof(musuh));
	memset(sudah,false,sizeof(sudah));
	adaans=true;
	cin>>nodes>>edge;
	for(int i=1;i<=nodes;i++)
	{
		ranks[i]=0;
		par[i]=i;
	}
	for(int i=1;i<=edge;i++)
	{
		int u,v,weight;
		cin>>u>>v>>weight;
		edgelist[weight].pb(mp(u,v));
	}
	for(auto edgebaru:edgelist[1])
		gabung(edgebaru.fi,edgebaru.se);
	for(auto edgebaru:edgelist[0])
	{
		if(connected(edgebaru.fi,edgebaru.se))
		{
			adaans=false;
			break;
		}
		int u=edgebaru.fi;
		int v=edgebaru.se;
		for(int ulang=1;ulang<=2;ulang++)
		{
			if(musuh[finds(u)]==-1)
				musuh[finds(u)]=finds(v);
			else
			{
				gabung(musuh[finds(u)],v);
			}
			swap(u,v);
		}
	}
	if(!adaans)
	{
		printf("0\n");
		return 0;
	}
	for(int i=1;i<=nodes;i++)
	{
		int now=finds(i);
		if(sudah[now]||sudah[finds(musuh[now])])
			continue;
		sudah[now]=true;
		if(musuh[now]!=-1)
		{
			sudah[finds(musuh[now])]=true;
		}
		if(ans==0)
			ans=1;
		else
			ans=modulo(ans*2LL);
	}
	cout<<ans<<endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
typedef long long LL;
const LL mods=1000000007LL;
const int MAXN=100000;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
int nodes,edge,ranks[MAXN+5],par[MAXN+5],musuh[MAXN+5];
vector <pii> edgelist[5];
LL ans=0;
bool adaans=true,sudah[MAXN+5];
LL modulo(LL angka){
	if(angka>=mods)
		angka%=mods;
	return angka;
}
int finds(int u){
	if(par[u]!=u)
		par[u]=finds(par[u]);
	return par[u];
}
bool connected(int u,int v){
	return finds(u)==finds(v);
}
void gabung(int titik1,int titik2){
	int u=finds(titik1);
	int v=finds(titik2);
	if(u==v)
		return;
	if(ranks[u]==ranks[v])
		ranks[u]++;
	if(ranks[u]>ranks[v])
	{
		par[v]=u;
		if(musuh[u]==-1)
			musuh[u]=musuh[v];
	}
	else
	{
		par[u]=v;
		if(musuh[v]==-1)
			musuh[v]=musuh[u];
	}
}
int main()
{
	memset(musuh,-1,sizeof(musuh));
	memset(sudah,false,sizeof(sudah));
	adaans=true;
	cin>>nodes>>edge;
	for(int i=1;i<=nodes;i++)
	{
		ranks[i]=0;
		par[i]=i;
	}
	for(int i=1;i<=edge;i++)
	{
		int u,v,weight;
		cin>>u>>v>>weight;
		edgelist[weight].pb(mp(u,v));
	}
	for(auto edgebaru:edgelist[1])
		gabung(edgebaru.fi,edgebaru.se);
	for(auto edgebaru:edgelist[0])
	{
		if(connected(edgebaru.fi,edgebaru.se))
		{
			adaans=false;
			break;
		}
		int u=edgebaru.fi;
		int v=edgebaru.se;
		for(int ulang=1;ulang<=2;ulang++)
		{
			if(musuh[finds(u)]==-1)
				musuh[finds(u)]=finds(v);
			else
				gabung(musuh[finds(u)],v);
			swap(u,v);
		}
	}
	if(!adaans)
	{
		printf("0\n");
		return 0;
	}
	for(int i=1;i<=nodes;i++)
	{
		if(sudah[finds(i)])
			continue;
		sudah[finds(i)]=true;
		sudah[finds(musuh[finds(i)])]=true;
		if(ans==0)
			ans=1;
		else
			ans=modulo(ans*2);
	}
	cout<<ans<<endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
typedef long long LL;
const LL mods=1000000007LL;
const int MAXN=100000;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
int nodes,edge,ranks[MAXN+5],par[MAXN+5],musuh[MAXN+5];
vector <pii> edgelist[5];
LL ans=0;
bool adaans=true,sudah[MAXN+5];
LL modulo(LL angka){
	if(angka>=mods)
		angka%=mods;
	return angka;
}
int finds(int u){
	if(par[u]!=u)
		par[u]=finds(par[u]);
	return par[u];
}
bool connected(int u,int v){
	return finds(u)==finds(v);
}
void gabung(int titik1,int titik2){
	int u=finds(titik1);
	int v=finds(titik2);
	if(u==v)
		return;
	if(ranks[u]==ranks[v])
		ranks[u]++;
	if(ranks[u]>ranks[v])
	{
		par[v]=u;
		if(musuh[u]==-1)
			musuh[u]=musuh[v];
	}
	else
	{
		par[u]=v;
		if(musuh[v]==-1)
			musuh[v]=musuh[u];
	}
}
int main()
{
	memset(musuh,-1,sizeof(musuh));
	memset(sudah,false,sizeof(sudah));
	adaans=true;
	cin>>nodes>>edge;
	for(int i=1;i<=nodes;i++)
	{
		ranks[i]=0;
		par[i]=i;
	}
	for(int i=1;i<=edge;i++)
	{
		int u,v,weight;
		cin>>u>>v>>weight;
		edgelist[weight].pb(mp(u,v));
	}
	for(auto edgebaru:edgelist[1])
		gabung(edgebaru.fi,edgebaru.se);
	for(auto edgebaru:edgelist[0])
	{
		if(connected(edgebaru.fi,edgebaru.se))
		{
			adaans=false;
			break;
		}
		int u=edgebaru.fi;
		int v=edgebaru.se;
		for(int ulang=1;ulang<=2;ulang++)
		{
			if(musuh[finds(u)]==-1)
				musuh[finds(u)]=finds(v);
			else
			{
				gabung(musuh[finds(u)],v);
			}
			swap(u,v);
		}
	}
	if(!adaans)
	{
		printf("0\n");
		return 0;
	}
	for(int i=1;i<=nodes;i++)
	{
		if(sudah[finds(i)])
			continue;
		sudah[finds(i)]=true;
		if(musuh[finds(i)]!=-1)
		{
			assert(!sudah[finds(musuh[finds(i)])]);
			sudah[finds(musuh[finds(i)])]=true;
		}
		if(ans==0)
			ans=1;
		else
			ans=modulo(ans*2LL);
	}
	cout<<ans<<endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
typedef long long LL;
const LL mods=1000000007LL;
const int MAXN=100000;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
int nodes,edge,ranks[MAXN+5],par[MAXN+5],musuh[MAXN+5];
vector <pii> edgelist[5];
LL ans=0;
bool adaans=true,sudah[MAXN+5];
LL modulo(LL angka){
	if(angka>=mods)
		angka%=mods;
	return angka;
}
int finds(int u){
	if(par[u]!=u)
		par[u]=finds(par[u]);
	return par[u];
}
bool connected(int u,int v){
	return finds(u)==finds(v);
}
void gabung(int titik1,int titik2){
	int u=finds(titik1);
	int v=finds(titik2);
	if(u==v)
		return;
	if(ranks[u]==ranks[v])
		ranks[u]++;
	if(ranks[u]>ranks[v])
	{
		par[v]=u;
		if(musuh[u]==-1)
			musuh[u]=musuh[v];
	}
	else
	{
		par[u]=v;
		if(musuh[v]==-1)
			musuh[v]=musuh[u];
	}
}
int main()
{
	memset(musuh,-1,sizeof(musuh));
	memset(sudah,false,sizeof(sudah));
	adaans=true;
	cin>>nodes>>edge;
	for(int i=1;i<=nodes;i++)
	{
		ranks[i]=0;
		par[i]=i;
	}
	for(int i=1;i<=edge;i++)
	{
		int u,v,weight;
		cin>>u>>v>>weight;
		edgelist[weight].pb(mp(u,v));
	}
	for(auto edgebaru:edgelist[1])
		gabung(edgebaru.fi,edgebaru.se);
	for(auto edgebaru:edgelist[0])
	{
		if(connected(edgebaru.fi,edgebaru.se))
		{
			adaans=false;
			break;
		}
		int u=edgebaru.fi;
		int v=edgebaru.se;
		for(int ulang=1;ulang<=2;ulang++)
		{
			if(musuh[finds(u)]==-1)
				musuh[finds(u)]=finds(v);
			else
			{
				gabung(musuh[finds(u)],v);
			}
			swap(u,v);
		}
	}
	if(!adaans)
	{
		printf("0\n");
		return 0;
	}
	for(int i=1;i<=nodes;i++)
	{
		if(sudah[finds(i)])
			continue;
		sudah[finds(i)]=true;
		sudah[finds(musuh[finds(i)])]=true;
		if(ans==0)
			ans=1;
		else
			ans=modulo(ans*2LL);
	}
	if(LL(nodes)*LL(nodes-1)/LL(2)==edge)
		ans=0;
	cout<<ans<<endl;
}


#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<set>
using namespace std;
typedef pair<int, int> pii;
typedef double lf;
typedef long long ll;
const int inf=0x3f3f3f3f, mod=1000000007;
int fa[100100], val[100100];

inline int read()
{
    int x=0,f=1; char ch=getchar();
    for (; ch<'0' || ch>'9'; ch=getchar()) if (ch=='-') f=-1;
    for (; ch>='0' && ch<='9'; ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}

int find(int x)
{
    if (fa[x]==x) return x;
    int t=find(fa[x]);
    val[x]^=val[fa[x]];
    return fa[x]=t;
}

void merge(int x, int y)
{
    int fx=find(x),fy=find(y);
    if (fx!=fy) fa[fy]=fx;
}

int main()
{
    int n=read(), k=read();
    for (int i=1; i<=n; i++) fa[i]=i;
    for (int i=1; i<=k; i++)
    {
        int u=read(), v=read(), w=read()^1;
        int fu=find(u), fv=find(v);
        if (fu!=fv)
        {
            fa[fv]=fu;
            val[fv]=val[u]^val[v]^w;
        }
        else
        {
            if (w && !(val[u]^val[v])) {puts("0"); return 0;}
            if (!w && val[u]^val[v]) {puts("0"); return 0;}
        }
    }
    int res=0, ans=1;
    for (int i=1; i<=n; i++) if (find(i)==i) res++;
    for (int i=1; i<=res-1; i++) ans=(ans*2)%mod;
    printf("%d\n",ans);
    return 0;
}


#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<set>
using namespace std;
typedef pair<int, int> pii;
typedef double lf;
typedef long long ll;
const int inf=0x3f3f3f3f, mod=1000000007;
int fa[100100], val[100100];

inline int read()
{
    int x=0,f=1; char ch=getchar();
    for (; ch<'0' || ch>'9'; ch=getchar()) if (ch=='-') f=-1;
    for (; ch>='0' && ch<='9'; ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}

int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void merge(int x, int y){int fx=find(x),fy=find(y); if (fx!=fy) fa[fy]=fx;}

int main()
{
    int n=read(), k=read();
    for (int i=1; i<=n; i++) fa[i]=i;
    for (int i=1; i<=k; i++)
    {
        int u=read(), v=read(), w=read()^1;
        int fu=find(u), fv=find(v);
        if (fu!=fv)
        {
            fa[fv]=fu;
            val[fv]=val[u]^val[v]^w;
        }
        else
        {
            if (w && !(val[u]^val[v])) {puts("0"); return 0;}
            if (!w && val[u]^val[v]) {puts("0"); return 0;}
        }
    }
    int res=0, ans=1;
    for (int i=1; i<=n; i++) if (find(i)==i) res++;
    for (int i=1; i<=res-1; i++) ans=(ans*2)%mod;
    printf("%d\n",ans);
    return 0;
}


#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<set>
using namespace std;
typedef pair<int, int> pii;
typedef double lf;
typedef long long ll;
const int inf=0x3f3f3f3f, mod=1000000007;
int fa[200200], flag[100100];
inline int read()
{
    int x=0,f=1; char ch=getchar();
    for (; ch<'0' || ch>'9'; ch=getchar()) if (ch=='-') f=-1;
    for (; ch>='0' && ch<='9'; ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}

int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void merge(int x, int y){int fx=find(x),fy=find(y); if (fx!=fy) fa[fy]=fx;}

int main()
{
    int n=read(), k=read();
    for (int i=1; i<=2*n; i++) fa[i]=i;
    for (int i=1; i<=k; i++)
    {
        int u=read(), v=read(), w=read();
        if (w==1)
        {
            if (flag[u] && flag[v] && find(u)!=find(v)) {printf("0\n"); return 0;}
            merge(u, v);
        }
        if (w==0)
        {
            if (flag[u] && flag[v] && find(u)==find(v)) {printf("0\n"); return 0;}
            merge(u, v+n); merge(v, u+n);
        }
        flag[u]=1; flag[v]=1;
    }
    int res=0, ans=1;
    for (int i=1; i<=n; i++) if (!flag[i]) res++;
    for (int i=1; i<=res-1; i++) ans=(ans*2)%mod;
    printf("%d\n",ans);
    return 0;
}


#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<set>
using namespace std;
typedef pair<int, int> pii;
typedef double lf;
typedef long long ll;
const int inf=0x3f3f3f3f, mod=1000000007;
int fa[100100], val[100100];

inline int read()
{
    int x=0,f=1; char ch=getchar();
    for (; ch<'0' || ch>'9'; ch=getchar()) if (ch=='-') f=-1;
    for (; ch>='0' && ch<='9'; ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}

int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void merge(int x, int y){int fx=find(x),fy=find(y); if (fx!=fy) fa[fy]=fx;}

int main()
{
    int n=read(), k=read();
    for (int i=1; i<=n; i++) fa[i]=i;
    for (int i=1; i<=k; i++)
    {
        int u=read(), v=read(), w=read()^1;
        int fu=find(u), fv=find(v);
        if (fu!=fv)
        {
            fa[fv]=fu;
            val[fv]=val[u]^val[v]^w;
        }
        else
        {
            if (w && val[fu]^val[fv]) {puts("0"); return 0;}
            if (!w && !(val[fu]^val[fv])) {puts("0"); return 0;}
        }
    }
    int res=0, ans=1;
    for (int i=1; i<=n; i++) if (find(i)==i) res++;
    for (int i=1; i<=res-1; i++) ans=(ans*2)%mod;
    printf("%d\n",ans);
    return 0;
}


#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<set>
using namespace std;
typedef pair<int, int> pii;
typedef double lf;
typedef long long ll;
const int inf=0x3f3f3f3f, mod=1000000007;
int fa[100100], val[100100];

inline int read()
{
    int x=0,f=1; char ch=getchar();
    for (; ch<'0' || ch>'9'; ch=getchar()) if (ch=='-') f=-1;
    for (; ch>='0' && ch<='9'; ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}

int find(int x)
{
    if (fa[x]==x) return x;
    int t=find(x);
    val[x]^=val[fa[x]];
    return fa[x]=t;
}

void merge(int x, int y)
{
    int fx=find(x),fy=find(y);
    if (fx!=fy) fa[fy]=fx;
}

int main()
{
    int n=read(), k=read();
    for (int i=1; i<=n; i++) fa[i]=i;
    for (int i=1; i<=k; i++)
    {
        int u=read(), v=read(), w=read()^1;
        int fu=find(u), fv=find(v);
        if (fu!=fv)
        {
            fa[fv]=fu;
            val[fv]=val[u]^val[v]^w;
        }
        else
        {
            if (w && !(val[u]^val[v])) {puts("0"); return 0;}
            if (!w && val[u]^val[v]) {puts("0"); return 0;}
        }
    }
    int res=0, ans=1;
    for (int i=1; i<=n; i++) if (find(i)==i) res++;
    for (int i=1; i<=res-1; i++) ans=(ans*2)%mod;
    printf("%d\n",ans);
    return 0;
}


#pragma comment (linker, "/STACK:128000000")
#define _CRT_SECURE_NO_WARNINGS
//#include "testlib.h"
#include <cstdio>
#include <cassert>
#include <algorithm>
#include <iostream>
#include <memory.h>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <bitset>
#include <deque>
//#include <unordered_map>
//#include <unordered_set>
#include <ctime>
#include <stack>
#include <queue>
#include <fstream>
using namespace std;
//#define FILENAME ""
#define mp make_pair
#define all(a) a.begin(), a.end()
typedef long long li;
typedef long double ld;
void solve();
void precalc();
clock_t start;
//int timer = 1;

bool todo = true;

int main() {
#ifdef room111
	freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
#else
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	//freopen(FILENAME".in", "r", stdin);
	//freopen(FILENAME ".out", "w", stdout);
#endif
	int t = 1;
	cout.sync_with_stdio(0);
	cin.tie(0);
	precalc();
	cout.precision(10);
	cout << fixed;
	//cin >> t;
	start = clock();
	int testNum = 1;
	while (t--) {
		//cout << "Case #" << testNum++ << ": ";
		solve();
		//++timer;
	}

#ifdef room111
	cerr << "\n\n" << (clock() - start) / 1.0 / CLOCKS_PER_SEC << "\n\n";
#endif

	return 0;
}

//BE CAREFUL: IS INT REALLY INT?

//#define int li

/*int pr[] = { 97, 2011 };
int mods[] = { 1000000007, 1000000009 };

const int C = 100500;

int powers[2][C];*/

int MOD = 1000000007;

int c[5010][5010];

//int catalan[200500];

int binpow(int q, int w, int mod) {
	if (!w)
		return 1;
	if (w & 1)
		return q * binpow(q, w - 1, mod) % mod;
	return binpow(q * q % mod, w / 2, mod);
}

void precalc() {

	/*for (int w = 0; w < 2; ++w) {
	powers[w][0] = 1;
	for (int j = 1; j < C; ++j) {
	powers[w][j] = (powers[w][j - 1] * 1LL * pr[w]) % mods[w];
	}
	}*/

	/*catalan[0] = 1;
	for (int n = 0; n < 200500 - 1; ++n) {
		catalan[n + 1] = catalan[n] * 2 * (2 * n + 1) % MOD * binpow(n + 2, MOD - 2, MOD) % MOD;
	}*/

	for (int i = 0; i < 5010; ++i) {
		c[i][i] = c[i][0] = 1;
		for (int j = 1; j < i; ++j) {
			c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % MOD;
		}
	}
}

int gcd(int q, int w) {
	while (w) {
		q %= w;
		swap(q, w);
	}
	return q;
}

#define int li

//int mod = 1000000007;

vector<int> dsu;

int findSet(int v) {
	if (dsu[v] == v)
		return v;
	return dsu[v] = findSet(dsu[v]);
}

vector<vector<int>> sets;

void merge(int q, int w) {
	q = findSet(q);
	w = findSet(w);
	if (sets[q].size() > sets[w].size()) {
		swap(q, w);
	}
	for (auto item : sets[q]) {
		sets[w].push_back(item);
	}
	sets[q].clear();
	dsu[q] = w;
}

void solve() {
	int n, m;
	cin >> n >> m;
	dsu.resize(n);
	sets.resize(n);
	for (int i = 0; i < n; ++i) {
		dsu[i] = i;
		sets[i].push_back(i);
	}

	vector<vector<pair<int, int>>> g(n);
	for (int i = 0; i < m; ++i) {
		int a, b, c;
		cin >> a >> b >> c;
		--a; --b;
		g[a].push_back(mp(b, c));
		g[b].push_back(mp(a, c));
	}

	vector<char> used(n, false);

	for (int i = 0; i < n; ++i) {
		int v = findSet(i);
		if (used[v]) {
			continue;
		}

		vector<vector<int>> vs(2);

		for (int cur : sets[v]) {
			for (auto edge : g[cur]) {
				if (used[edge.first]) {
					continue;
				}
				if (findSet(cur) == findSet(edge.first) && edge.second == 0) {
					cout << "0\n";
					return;
				}
				vs[edge.second].push_back(findSet(edge.first));
			}
		}

		if (vs[0].size() + vs[1].size() == 0) {
			continue;
		}

		used[v] = true;
		for (int cur : sets[v]) {
			used[cur] = true;
		}

		for (int w = 0; w < 2; ++w) {
			sort(all(vs[w]));
			vs[w].erase(unique(all(vs[w])), vs[w].end());
		}
		for (auto item : vs[0]) {
			auto it = lower_bound(all(vs[1]), item);
			if (it != vs[1].end() && *it == item) {
				cout << "0\n";
				return;
			}
		}

		for (int w = 0; w < 2; ++w) {
			for (int i = 1; i < vs[w].size(); ++i) {
				merge(vs[w][0], vs[w][1]);
			}
		}
		if (vs[0].size() > 0 && vs[1].size() > 0) {
			int q = findSet(vs[0][0]), w = findSet(vs[1][0]);
			g[q].push_back(mp(w, 0));
			g[w].push_back(mp(q, 0));
		}

	}

	int cnt = 0;
	for (int i = 0; i < n; ++i) {
		if (!used[i] && findSet(i) == i) {
			++cnt;
		}
	}

	int res = cnt + 1;

	if (cnt == 1) {
		res = 1;
	}
	if (cnt == 2) {
		res = 2;
	}

	cout << res << "\n";

}


#pragma comment (linker, "/STACK:128000000")
#define _CRT_SECURE_NO_WARNINGS
//#include "testlib.h"
#include <cstdio>
#include <cassert>
#include <algorithm>
#include <iostream>
#include <memory.h>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <bitset>
#include <deque>
//#include <unordered_map>
//#include <unordered_set>
#include <ctime>
#include <stack>
#include <queue>
#include <fstream>
using namespace std;
//#define FILENAME ""
#define mp make_pair
#define all(a) a.begin(), a.end()
typedef long long li;
typedef long double ld;
void solve();
void precalc();
clock_t start;
//int timer = 1;

bool todo = true;

int main() {
#ifdef room111
	freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
#else
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	//freopen(FILENAME".in", "r", stdin);
	//freopen(FILENAME ".out", "w", stdout);
#endif
	int t = 1;
	cout.sync_with_stdio(0);
	cin.tie(0);
	precalc();
	cout.precision(10);
	cout << fixed;
	//cin >> t;
	start = clock();
	int testNum = 1;
	while (t--) {
		//cout << "Case #" << testNum++ << ": ";
		solve();
		//++timer;
	}

#ifdef room111
	cerr << "\n\n" << (clock() - start) / 1.0 / CLOCKS_PER_SEC << "\n\n";
#endif

	return 0;
}

//BE CAREFUL: IS INT REALLY INT?

//#define int li

/*int pr[] = { 97, 2011 };
int mods[] = { 1000000007, 1000000009 };

const int C = 100500;

int powers[2][C];*/

int MOD = 1000000007;

int c[5010][5010];

//int catalan[200500];

int binpow(int q, int w, int mod) {
	if (!w)
		return 1;
	if (w & 1)
		return q * binpow(q, w - 1, mod) % mod;
	return binpow(q * q % mod, w / 2, mod);
}

void precalc() {

	/*for (int w = 0; w < 2; ++w) {
	powers[w][0] = 1;
	for (int j = 1; j < C; ++j) {
	powers[w][j] = (powers[w][j - 1] * 1LL * pr[w]) % mods[w];
	}
	}*/

	/*catalan[0] = 1;
	for (int n = 0; n < 200500 - 1; ++n) {
		catalan[n + 1] = catalan[n] * 2 * (2 * n + 1) % MOD * binpow(n + 2, MOD - 2, MOD) % MOD;
	}*/

	for (int i = 0; i < 5010; ++i) {
		c[i][i] = c[i][0] = 1;
		for (int j = 1; j < i; ++j) {
			c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % MOD;
		}
	}
}

int gcd(int q, int w) {
	while (w) {
		q %= w;
		swap(q, w);
	}
	return q;
}

#define int li

//int mod = 1000000007;

vector<int> dsu;

int findSet(int v) {
	if (dsu[v] == v)
		return v;
	return dsu[v] = findSet(dsu[v]);
}

vector<vector<int>> sets;

void merge(int q, int w) {
	q = findSet(q);
	w = findSet(w);
	if (sets[q].size() > sets[w].size()) {
		swap(q, w);
	}
	for (auto item : sets[q]) {
		sets[w].push_back(item);
	}
	sets[q].clear();
	dsu[q] = w;
}

void solve() {
	int n, m;
	cin >> n >> m;
	dsu.resize(n);
	sets.resize(n);
	for (int i = 0; i < n; ++i) {
		dsu[i] = i;
		sets[i].push_back(i);
	}

	vector<vector<pair<int, int>>> g(n);
	for (int i = 0; i < m; ++i) {
		int a, b, c;
		cin >> a >> b >> c;
		--a; --b;
		g[a].push_back(mp(b, c));
		g[b].push_back(mp(a, c));
	}

	vector<char> used(n, false);

	for (int i = 0; i < n; ++i) {
		int v = findSet(i);
		if (used[v]) {
			continue;
		}

		vector<vector<int>> vs(2);

		for (int cur : sets[v]) {
			for (auto edge : g[cur]) {
				if (used[edge.first]) {
					continue;
				}
				vs[edge.second].push_back(findSet(edge.first));
			}
		}

		if (vs[0].size() + vs[1].size() == 0) {
			continue;
		}

		used[v] = true;
		for (int cur : sets[v]) {
			used[cur] = true;
		}

		for (int w = 0; w < 2; ++w) {
			sort(all(vs[w]));
			vs[w].erase(unique(all(vs[w])), vs[w].end());
		}
		for (auto item : vs[0]) {
			auto it = lower_bound(all(vs[1]), item);
			if (it != vs[1].end() && *it == item) {
				cout << "0\n";
				return;
			}
		}

		for (int w = 0; w < 2; ++w) {
			for (int i = 1; i < vs[w].size(); ++i) {
				merge(vs[w][0], vs[w][1]);
			}
		}
		if (vs[0].size() > 0 && vs[1].size() > 0) {
			int q = findSet(vs[0][0]), w = findSet(vs[1][0]);
			g[q].push_back(mp(w, 0));
			g[w].push_back(mp(q, 0));
		}

	}

	int cnt = 0;
	for (int i = 0; i < n; ++i) {
		if (!used[i] && findSet(i) == i) {
			++cnt;
		}
	}

	int res = cnt + 1;

	if (cnt == 1) {
		res = 1;
	}

	cout << res << "\n";

}


#pragma comment (linker, "/STACK:128000000")
#define _CRT_SECURE_NO_WARNINGS
//#include "testlib.h"
#include <cstdio>
#include <cassert>
#include <algorithm>
#include <iostream>
#include <memory.h>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <bitset>
#include <deque>
//#include <unordered_map>
//#include <unordered_set>
#include <ctime>
#include <stack>
#include <queue>
#include <fstream>
using namespace std;
//#define FILENAME ""
#define mp make_pair
#define all(a) a.begin(), a.end()
typedef long long li;
typedef long double ld;
void solve();
void precalc();
clock_t start;
//int timer = 1;

bool todo = true;

int main() {
#ifdef room111
	freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
#else
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	//freopen(FILENAME".in", "r", stdin);
	//freopen(FILENAME ".out", "w", stdout);
#endif
	int t = 1;
	cout.sync_with_stdio(0);
	cin.tie(0);
	precalc();
	cout.precision(10);
	cout << fixed;
	//cin >> t;
	start = clock();
	int testNum = 1;
	while (t--) {
		//cout << "Case #" << testNum++ << ": ";
		solve();
		//++timer;
	}

#ifdef room111
	cerr << "\n\n" << (clock() - start) / 1.0 / CLOCKS_PER_SEC << "\n\n";
#endif

	return 0;
}

//BE CAREFUL: IS INT REALLY INT?

//#define int li

/*int pr[] = { 97, 2011 };
int mods[] = { 1000000007, 1000000009 };

const int C = 100500;

int powers[2][C];*/

int MOD = 1000000007;

int c[5010][5010];

//int catalan[200500];

int binpow(int q, int w, int mod) {
	if (!w)
		return 1;
	if (w & 1)
		return q * binpow(q, w - 1, mod) % mod;
	return binpow(q * q % mod, w / 2, mod);
}

void precalc() {

	/*for (int w = 0; w < 2; ++w) {
	powers[w][0] = 1;
	for (int j = 1; j < C; ++j) {
	powers[w][j] = (powers[w][j - 1] * 1LL * pr[w]) % mods[w];
	}
	}*/

	/*catalan[0] = 1;
	for (int n = 0; n < 200500 - 1; ++n) {
		catalan[n + 1] = catalan[n] * 2 * (2 * n + 1) % MOD * binpow(n + 2, MOD - 2, MOD) % MOD;
	}*/

	for (int i = 0; i < 5010; ++i) {
		c[i][i] = c[i][0] = 1;
		for (int j = 1; j < i; ++j) {
			c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % MOD;
		}
	}
}

int gcd(int q, int w) {
	while (w) {
		q %= w;
		swap(q, w);
	}
	return q;
}

#define int li

//int mod = 1000000007;

vector<int> dsu;

int findSet(int v) {
	if (dsu[v] == v)
		return v;
	return dsu[v] = findSet(dsu[v]);
}

vector<vector<int>> sets;

void merge(int q, int w) {
	q = findSet(q);
	w = findSet(w);
	if (sets[q].size() > sets[w].size()) {
		swap(q, w);
	}
	for (auto item : sets[q]) {
		sets[w].push_back(item);
	}
	sets[q].clear();
	dsu[q] = w;
}

void solve() {
	int n, m;
	cin >> n >> m;
	dsu.resize(n);
	sets.resize(n);
	for (int i = 0; i < n; ++i) {
		dsu[i] = i;
		sets[i].push_back(i);
	}

	vector<vector<pair<int, int>>> g(n);
	for (int i = 0; i < m; ++i) {
		int a, b, c;
		cin >> a >> b >> c;
		--a; --b;
		g[a].push_back(mp(b, c));
		g[b].push_back(mp(a, c));
	}

	vector<char> used(n, false);

	for (int i = 0; i < n; ++i) {
		int v = findSet(i);
		if (used[v]) {
			continue;
		}

		vector<vector<int>> vs(2);

		for (int cur : sets[v]) {
			for (auto edge : g[cur]) {
				if (used[edge.first]) {
					continue;
				}
				vs[edge.second].push_back(findSet(edge.first));
			}
		}

		if (vs[0].size() + vs[1].size() == 0) {
			continue;
		}

		used[v] = true;
		for (int cur : sets[v]) {
			used[cur] = true;
		}

		for (int w = 0; w < 2; ++w) {
			sort(all(vs[w]));
			vs[w].erase(unique(all(vs[w])), vs[w].end());
		}
		for (auto item : vs[0]) {
			auto it = lower_bound(all(vs[1]), item);
			if (it != vs[1].end() && *it == item) {
				cout << "0\n";
				return;
			}
		}

		for (int w = 0; w < 2; ++w) {
			for (int i = 1; i < vs[w].size(); ++i) {
				merge(vs[w][0], vs[w][1]);
			}
		}
		if (vs[0].size() > 0 && vs[1].size() > 0) {
			int q = findSet(vs[0][0]), w = findSet(vs[1][0]);
			g[q].push_back(mp(w, 0));
			g[w].push_back(mp(q, 0));
		}

	}

	int cnt = 0;
	for (int i = 0; i < n; ++i) {
		if (!used[i] && findSet(i) == i) {
			++cnt;
		}
	}

	int res = cnt + 1;

	if (cnt == 1) {
		res = 1;
	}
	if (cnt == 2) {
		res = 2;
	}

	cout << res << "\n";

}


#pragma comment (linker, "/STACK:128000000")
#define _CRT_SECURE_NO_WARNINGS
//#include "testlib.h"
#include <cstdio>
#include <cassert>
#include <algorithm>
#include <iostream>
#include <memory.h>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <bitset>
#include <deque>
//#include <unordered_map>
//#include <unordered_set>
#include <ctime>
#include <stack>
#include <queue>
#include <fstream>
using namespace std;
//#define FILENAME ""
#define mp make_pair
#define all(a) a.begin(), a.end()
typedef long long li;
typedef long double ld;
void solve();
void precalc();
clock_t start;
//int timer = 1;

bool todo = true;

int main() {
#ifdef room111
	freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
#else
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	//freopen(FILENAME".in", "r", stdin);
	//freopen(FILENAME ".out", "w", stdout);
#endif
	int t = 1;
	cout.sync_with_stdio(0);
	cin.tie(0);
	precalc();
	cout.precision(10);
	cout << fixed;
	//cin >> t;
	start = clock();
	int testNum = 1;
	while (t--) {
		//cout << "Case #" << testNum++ << ": ";
		solve();
		//++timer;
	}

#ifdef room111
	cerr << "\n\n" << (clock() - start) / 1.0 / CLOCKS_PER_SEC << "\n\n";
#endif

	return 0;
}

//BE CAREFUL: IS INT REALLY INT?

//#define int li

/*int pr[] = { 97, 2011 };
int mods[] = { 1000000007, 1000000009 };

const int C = 100500;

int powers[2][C];*/

int MOD = 1000000007;

int c[5010][5010];

//int catalan[200500];

int binpow(int q, int w, int mod) {
	if (!w)
		return 1;
	if (w & 1)
		return q * binpow(q, w - 1, mod) % mod;
	return binpow(q * q % mod, w / 2, mod);
}

void precalc() {

	/*for (int w = 0; w < 2; ++w) {
	powers[w][0] = 1;
	for (int j = 1; j < C; ++j) {
	powers[w][j] = (powers[w][j - 1] * 1LL * pr[w]) % mods[w];
	}
	}*/

	/*catalan[0] = 1;
	for (int n = 0; n < 200500 - 1; ++n) {
		catalan[n + 1] = catalan[n] * 2 * (2 * n + 1) % MOD * binpow(n + 2, MOD - 2, MOD) % MOD;
	}*/

	for (int i = 0; i < 5010; ++i) {
		c[i][i] = c[i][0] = 1;
		for (int j = 1; j < i; ++j) {
			c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % MOD;
		}
	}
}

int gcd(int q, int w) {
	while (w) {
		q %= w;
		swap(q, w);
	}
	return q;
}

#define int li

//int mod = 1000000007;

vector<int> dsu;

int findSet(int v) {
	if (dsu[v] == v)
		return v;
	return dsu[v] = findSet(dsu[v]);
}

vector<vector<int>> sets;

void merge(int q, int w) {
	q = findSet(q);
	w = findSet(w);
	if (sets[q].size() > sets[w].size()) {
		swap(q, w);
	}
	for (auto item : sets[q]) {
		sets[w].push_back(item);
	}
	sets[q].clear();
	dsu[q] = w;
}

void solve() {
	int n, m;
	cin >> n >> m;
	dsu.resize(n);
	sets.resize(n);
	for (int i = 0; i < n; ++i) {
		dsu[i] = i;
		sets[i].push_back(i);
	}

	vector<vector<pair<int, int>>> g(n);
	for (int i = 0; i < m; ++i) {
		int a, b, c;
		cin >> a >> b >> c;
		--a; --b;
		g[a].push_back(mp(b, c));
		g[b].push_back(mp(a, c));
	}

	vector<char> used(n, false);

	for (int i = 0; i < n; ++i) {
		int v = findSet(i);
		if (used[v]) {
			continue;
		}

		vector<vector<int>> vs(2);

		for (int cur : sets[v]) {
			for (auto edge : g[cur]) {
				if (used[edge.first]) {
					continue;
				}
				/*if (findSet(cur) == findSet(edge.first) && edge.second == 0) {
					cout << "0\n";
					return;
				}*/
				vs[edge.second].push_back(findSet(edge.first));
			}
		}

		if (vs[0].size() + vs[1].size() == 0) {
			continue;
		}

		used[v] = true;
		for (int cur : sets[v]) {
			used[cur] = true;
		}

		for (int w = 0; w < 2; ++w) {
			sort(all(vs[w]));
			vs[w].erase(unique(all(vs[w])), vs[w].end());
		}
		for (auto item : vs[0]) {
			auto it = lower_bound(all(vs[1]), item);
			if (it != vs[1].end() && *it == item) {
				cout << "0\n";
				return;
			}
		}

		for (int w = 0; w < 2; ++w) {
			for (int i = 1; i < vs[w].size(); ++i) {
				merge(vs[w][0], vs[w][i]);
			}
		}
		if (vs[0].size() > 0 && vs[1].size() > 0) {
			int q = findSet(vs[0][0]), w = findSet(vs[1][0]);
			g[q].push_back(mp(w, 0));
			g[w].push_back(mp(q, 0));
		}

	}

	for (int i = 0; i < n; ++i) {
		for (auto item : g[i]) {
			int to = item.first;
			if (findSet(i) == findSet(to) && item.second == 0) {
				cout << "0\n";
				return;
			}
		}
	}

	int cnt = 0;
	for (int i = 0; i < n; ++i) {
		if (!used[i] && findSet(i) == i) {
			++cnt;
		}
	}

	int res = cnt + 1;

	if (cnt == 1) {
		res = 1;
	}
	if (cnt == 2) {
		res = 2;
	}

	cout << res << "\n";

}


#pragma comment (linker, "/STACK:128000000")
#define _CRT_SECURE_NO_WARNINGS
//#include "testlib.h"
#include <cstdio>
#include <cassert>
#include <algorithm>
#include <iostream>
#include <memory.h>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <bitset>
#include <deque>
//#include <unordered_map>
//#include <unordered_set>
#include <ctime>
#include <stack>
#include <queue>
#include <fstream>
using namespace std;
//#define FILENAME ""
#define mp make_pair
#define all(a) a.begin(), a.end()
typedef long long li;
typedef long double ld;
void solve();
void precalc();
clock_t start;
//int timer = 1;

bool todo = true;

int main() {
#ifdef room111
	freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
#else
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	//freopen(FILENAME".in", "r", stdin);
	//freopen(FILENAME ".out", "w", stdout);
#endif
	int t = 1;
	cout.sync_with_stdio(0);
	cin.tie(0);
	precalc();
	cout.precision(10);
	cout << fixed;
	//cin >> t;
	start = clock();
	int testNum = 1;
	while (t--) {
		//cout << "Case #" << testNum++ << ": ";
		solve();
		//++timer;
	}

#ifdef room111
	cerr << "\n\n" << (clock() - start) / 1.0 / CLOCKS_PER_SEC << "\n\n";
#endif

	return 0;
}

//BE CAREFUL: IS INT REALLY INT?

//#define int li

/*int pr[] = { 97, 2011 };
int mods[] = { 1000000007, 1000000009 };

const int C = 100500;

int powers[2][C];*/

int MOD = 1000000007;

int c[5010][5010];

//int catalan[200500];

int binpow(int q, int w, int mod) {
	if (!w)
		return 1;
	if (w & 1)
		return q * binpow(q, w - 1, mod) % mod;
	return binpow(q * q % mod, w / 2, mod);
}

void precalc() {

	/*for (int w = 0; w < 2; ++w) {
	powers[w][0] = 1;
	for (int j = 1; j < C; ++j) {
	powers[w][j] = (powers[w][j - 1] * 1LL * pr[w]) % mods[w];
	}
	}*/

	/*catalan[0] = 1;
	for (int n = 0; n < 200500 - 1; ++n) {
		catalan[n + 1] = catalan[n] * 2 * (2 * n + 1) % MOD * binpow(n + 2, MOD - 2, MOD) % MOD;
	}*/

	for (int i = 0; i < 5010; ++i) {
		c[i][i] = c[i][0] = 1;
		for (int j = 1; j < i; ++j) {
			c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % MOD;
		}
	}
}

int gcd(int q, int w) {
	while (w) {
		q %= w;
		swap(q, w);
	}
	return q;
}

#define int li

//int mod = 1000000007;

vector<int> dsu;

int findSet(int v) {
	if (dsu[v] == v)
		return v;
	return dsu[v] = findSet(dsu[v]);
}

void merge(int q, int w) {
	q = findSet(q);
	w = findSet(w);
	if (rand() & 1)
		dsu[q] = w;
	else
		dsu[w] = q;
}

vector<vector<int>> G;

vector<int> used;

bool dfs(int v, int ch) {
	if (used[v] != -1) {
		return used[v] == ch;
	}
	used[v] = ch;
	bool res = true;
	for (int to : G[v]) {
		res &= dfs(to, ch ^ 1);
	}
	return res;
}

void solve() {
	int n, m;
	cin >> n >> m;
	dsu.resize(n);
	G.resize(n);
	for (int i = 0; i < n; ++i) {
		dsu[i] = i;
	}

	vector<vector<pair<int, int>>> g(n);
	for (int i = 0; i < m; ++i) {
		int a, b, c;
		cin >> a >> b >> c;
		--a; --b;
		g[a].push_back(mp(b, c));
		g[b].push_back(mp(a, c));
	}

	for (int i = 0; i < n; ++i) {
		for (auto item : g[i]) {
			int to = item.first;
			if (item.second == 1) {
				merge(i, to);
			}
		}
	}

	for (int i = 0; i < n; ++i) {
		for (auto item : g[i]) {
			int to = item.first;
			if (item.second == 0) {
				if (findSet(i) == findSet(to)) {
					cout << "0\n";
					return;
				}
				G[findSet(i)].push_back(findSet(to));
				G[findSet(to)].push_back(findSet(i));
			}
		}
	}

	used.assign(n, -1);

	int cnt = 0;

	for (int i = 0; i < n; ++i) {
		if (i != findSet(i)) {
			continue;
		}
		if (used[i] != -1) {
			continue;
		}
		if (!dfs(i, 0)) {
			cout << "0\n";
			return;
		}
		++cnt;
	}

	int res = 1;
	for (int i = 0; i < cnt - 1; ++i) {
		res = res * 2 % MOD;
	}

	cout << res << "\n";

}


#include<bits/stdc++.h>
#define MAXN 1000010
#define MAXE 1000010
#define MOD 1000000007
using namespace std;
int N,M;
int col[MAXN];
long long ans;

vector<pair<int,int>>e[MAXN];

void dfs(int x)
{
    for(int i=0;i<e[x].size();i++)
    {
        int to = e[x][i].first;
        int des;
        if((col[x]==1&&!e[x][i].second)||(col[x]==2&&e[x][i].second))
        {
            des = 2;
        }
        else des = 1;
        if(!col[to])
        {
            col[to] = des;dfs(to);
        }
        else if(col[to]!=des)
            ans = 0;
    }
}

int main()
{
    //freopen("G.in","r",stdin);
    ans = 1;
    scanf("%d %d",&N,&M);
    for(int i=1;i<=M;i++)
    {
        int u,v,c;scanf("%d %d %d",&u,&v,&c);
        e[u].push_back({v,c});
        e[v].push_back({u,c});
    }
    bool flg=0;
    for(int i=1;i<=N;i++)
    {
        if(!col[i])
        {
            if(flg)ans = ans * 2 % MOD;
            flg=1;
            col[i]=1;
            dfs(i);
        }
    }
    cout<<ans<<endl;

    return 0;
}


#include<bits/stdc++.h>
#define MAXN 1000010
#define MAXE 1000010
#define MOD 1000000007
using namespace std;
int N,M;
int col[MAXN];
long long ans;

vector<pair<int,int>>e[MAXN];

void dfs(int x)
{
    for(int i=0;i<e[x].size();i++)
    {
        int to = e[x][i].first;
        int des;
        if((col[x]==1&&e[x][i].second)||(col[x]==2&&!e[x][i].second))
        {
            des = 2;
        }
        else des = 1;
        if(!col[to])
        {
            col[to] = des;dfs(to);
        }
        else if(col[to]!=des)ans = 0;
    }
}

int main()
{
    //freopen("G.in","r",stdin);
    ans=1;
    scanf("%d %d",&N,&M);
    for(int i=1;i<=M;i++)
    {
        int u,v,c;scanf("%d %d %d",&u,&v,&c);
        e[u].push_back({v,c});
        e[v].push_back({u,c});
    }
    bool flg=0;
    for(int i=1;i<=N;i++)
    {
        if(!col[i])
        {
            if(flg)ans = ans * 2 % MOD;
            flg=1;
            col[i]=1;
            dfs(1);
        }
    }
    cout<<ans<<endl;

    return 0;
}


#include<bits/stdc++.h>
#define MAXN 1000010
#define MAXE 1000010
#define MOD 1000000007
using namespace std;
int N,M;
int col[MAXN];
long long ans;

vector<pair<int,int>>e[MAXN];

void dfs(int x)
{
    for(int i=0;i<e[x].size();i++)
    {
        int to = e[x][i].first;
        int des;
        if((col[x]==1&&!e[x][i].second)||(col[x]==2&&e[x][i].second))
        {
            des = 2;
        }
        else des = 1;
        if(!col[to])
        {
            col[to] = des;dfs(to);
        }
        else if(col[to]!=des)
            ans = 0;
    }
}

int main()
{
    //freopen("G.in","r",stdin);
    ans = 1;
    scanf("%d %d",&N,&M);
    for(int i=1;i<=M;i++)
    {
        int u,v,c;scanf("%d %d %d",&u,&v,&c);
        e[u].push_back({v,c});
        e[v].push_back({u,c});
    }
    bool flg=0;
    for(int i=1;i<=N;i++)
    {
        if(!col[i])
        {
            if(flg)ans = ans * 2 % MOD;
            flg=1;
            col[i]=1;
            dfs(1);
        }
    }
    cout<<ans<<endl;

    return 0;
}


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

ll n,m,par[N],mark[N],ans;
vector <ll> e[N];
vector <pair<ll,ll> > ed;

ll root(ll x){if(par[x]<0)return x;return par[x]=root(par[x]);}
void merge(ll x,ll y){if(par[x]==par[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)?2ll:1ll),dfs(e[x][i]);
    }
}

int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++)par[i]=-i;
    for(int i=0;i<m;i++)
    {
        ll v,u,p;
        cin>>v>>u>>p;
        if(p)merge(v,u);
        else ed.push_back({v,u});
    }
    for(int i=0;i<ed.size();i++)
    {
        if(root(ed[i].first)==root(ed[i].second))return cout<<0,0;
        e[-par[root(ed[i].first)]].push_back(-par[root(ed[i].second)]);
        e[-par[root(ed[i].second)]].push_back(-par[root(ed[i].first)]);
    }
    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;
}