#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;
 
#define fi first
#define se second
#define mp make_pair
#define pb push_back
 
typedef long long ll;
typedef pair<int,int> ii;
typedef vector<int> vi;
typedef unsigned long long ull;
typedef long double ld; 
typedef tree<ii, null_type, less<ii>, rb_tree_tag, tree_order_statistics_node_update> pbds;

vector<int> fact;
vector<int> ifact;
vector<int> inv;
vector<int> pow2;
const int MOD = 998244353;
int add(int a, int b)
{
	a+=b;
	while(a>=MOD) a-=MOD;
	return a;
}
int mult(int a, int b)
{
	return (a*1LL*b)%MOD;
}
int modpow(int a, int b)
{
	int r=1;
	while(b)
	{
		if(b&1) r=mult(r,a);
		a=mult(a,a);
		b>>=1;
	}
	return r;
}
int choose(int a, int b)
{
	if(a<b) return 0;
	if(b==0) return 1;
	if(a==b) return 1;
	return mult(fact[a],mult(ifact[b],ifact[a-b]));
}
int inverse(int a)
{
	return modpow(a,MOD-2);
}
void init(int _n)
{
	fact.clear(); ifact.clear(); inv.clear(); pow2.clear();
	fact.resize(_n+1);
	ifact.resize(_n+1);
	inv.resize(_n+1);
	pow2.resize(_n+1);
	pow2[0]=1;
	ifact[0]=1;
	fact[0]=1;
	for(int i=1;i<=_n;i++)
	{
		pow2[i]=add(pow2[i-1],pow2[i-1]);
		fact[i]=mult(fact[i-1],i);
		//ifact[i]=mult(ifact[i-1],inv[i]);
	}
	ifact[_n] = inverse(fact[_n]);
	for(int i=_n-1;i>=1;i--)
	{
		ifact[i] = mult(ifact[i + 1], i + 1);
	}
	for(int i=1;i<=_n;i++)
	{
		inv[i] = mult(fact[i-1],ifact[i]);
	}
}

map<ii,int> ma;

int get(int x, int y)
{
	if(ma.find(mp(x,y))==ma.end()) return -1;
	else return ma[mp(x,y)];
}

int a[222222];
int dp[222222][2];

int main()
{
	ios_base::sync_with_stdio(0); cin.tie(0);
	memset(a,-1,sizeof(a));
	init(455555);
	int n,m; cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		int x,y,c; cin>>x>>y>>c; x--; y--;
		ma[mp(x,y)]=c;
	}
	int ans = 1;
	ll tot = 0;
	for(int i=1;i<=n-3;i++) tot+=i;
	tot%=(MOD-1); 
	ans = modpow(2, tot);
	for(auto sq:ma)
	{
		int x=sq.fi.fi; int y=sq.fi.se; int val=sq.se;
		int z = get(y,x);
		if(max(x,y)-min(x,y)<3) continue;
		if(z!=-1)
		{
			if(z!=val)
			{
				cout<<0<<'\n'; return 0;
			}
			if(x<y) ans=mult(ans,inv[2]);
		}
		else if(z==-1)
		{
			ans = mult(ans, inv[2]);
		}
	}
	ans = mult(ans, modpow(2, n-2));
	for(auto sq:ma)
	{
		int x=sq.fi.fi; int y=sq.fi.se; int val=sq.se;
		int z = get(y,x);
		if(max(x,y)-min(x,y)!=2) continue;
		if(z!=-1)
		{
			a[(x+y)/2] = z^val;
			if(x<y) ans=mult(ans,inv[2]);
		}
		else if(z==-1)
		{
			ans = mult(ans, inv[2]);
		}
	}
	{
		int zero_zero=get(0,0);
		if(zero_zero==-1)
		{
			dp[0][0]=dp[0][1]=1;
		}
		else dp[0][zero_zero]=1;
	}
	//cerr<<ans<<'\n';
	for(int i=0;i+1<n;i++)
	{
		for(int j=0;j<2;j++)
		{
			if(dp[i][j]==0) continue;
			int v=dp[i][j];
			int A[2][2];
			memset(A,-1,sizeof(A));
			A[0][0]=j;
			A[0][1]=get(i,i+1);
			A[1][0]=get(i+1,i);
			A[1][1]=get(i+1,i+1);
			if(A[1][1]!=-1&&a[i+1]!=-1&&a[i+1]!=A[1][1])
			{
				cout<<0<<'\n'; return 0;
			}
			if(a[i+1]!=-1) A[1][1]=a[i+1];
			int ct[2]={0,0};
			for(int z=0;z<16;z++)
			{
				int bit=z;
				bool pos=1; int lastbit=0;
				if(__builtin_popcount(z)%2==1) continue;
				for(int k=0;k<2;k++)
				{
					for(int l=0;l<2;l++)
					{
						int cur=bit&1;
						if(A[k][l]==-1||A[k][l]==cur)
						{
							
						}
						else
						{
							pos=0; break;
						}
						if(k==1&&l==1) lastbit=cur;
						bit>>=1;
					}
				}
				if(pos) ct[lastbit]++;
			}
			for(int z=0;z<2;z++)
			{
				dp[i+1][z] = add(dp[i+1][z], mult(v, ct[z]));
			}
			//cerr<<"DP "<<i<<' '<<j<<" : "<<dp[i][j]<<'\n';
		}
	}
	//cerr<<"DP "<<n-1<<' '<<0<<' '<<dp[n-1][0]<<'\n';
	//cerr<<"DP "<<n-1<<' '<<1<<' '<<dp[n-1][1]<<'\n';
	cout<<mult(ans,add(dp[n-1][0],dp[n-1][1]))<<'\n';
}


Measured memory_bytes: 12160