#include <bits/stdc++.h>
using namespace std;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for(auto it : P) { s << "<" << it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for(auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s << endl; }


template<int MOD> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr int getmod() { return MOD; }
    constexpr Fp operator - () const noexcept {
        return val ? MOD - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b; swap(a, b);
            u -= t * v; swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) noexcept {
        return os << x.val;
    }
    friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(a, n / 2);
        t = t * t;
        if (n & 1) t = t * a;
        return t;
    }
};
const int MOD = 998244353;
using mint = Fp<MOD>;
using pint = pair<int,int>;

long long N, M;
map<pint,int> fi;

mint solve() {
    // 斜めの自由度を先に計算
    long long jiyudo = (N - 1) * (N - 2) / 2;
    set<pint> alr;
    for (auto it : fi) {
        auto p = it.first;
        if (alr.count(p)) continue;
        if (abs(p.first - p.second) >= 3) {
            if (fi.count({p.second, p.first})) {
                if (fi[p] != fi[{p.second, p.first}]) return 0;
            }
            --jiyudo;
        }
        else if (abs(p.first - p.second) == 2) {
            pint q = {p.second, p.first};
            pint c = {(p.first+p.second)/2, (p.first+p.second)/2};
            if (fi.count(p) && fi.count(q)) {
                if (fi.count(c)) {
                    if ((fi[p]+fi[q]+fi[c]) % 2 != 0) return 0;
                }
                fi[c] = fi[p]^fi[q];
            }
            --jiyudo;
        }
        alr.insert(p); alr.insert({p.second, p.first});
    }

    set<int> can;
    for (int bit = 0; bit < (1<<4); ++bit) {
        if (__builtin_popcount(bit) % 2 != 0) continue;
        can.insert(bit);
    }
    vector<vector<mint>> dp(N+1, vector<mint>(1<<4, 0));
    for (auto bit : can) {
        bool ok = true;
        for (int i = 0; i < 4; ++i) {
            pint p(i/2, i%2);
            if (fi.count(p)) if ( ((bit>>i)&1) ^ fi[p] ) ok = false;
        }
        if (ok) dp[0][bit] = 1;
    }
    for (int t = 0; t < N-2; ++t) {
        for (auto bit : can) {
            if (dp[t][bit] == 0) continue;
            for (auto bit2 : can) {
                if ( ((bit>>3)&1) ^ ((bit2>>0)&1) ) continue;
                bool ok = true;
                for (int i = 0; i < 4; ++i) {
                    pint p(t+1+i/2, t+1+i%2);
                    if (fi.count(p)) if (((bit2>>i)&1) ^ fi[p]) ok = false;
                }
                if (ok) dp[t+1][bit2] += dp[t][bit];
            }
        }
    }
    mint res = 0;
    for (int bit = 0; bit < (1<<4); ++bit) res += dp[N-2][bit];
    return res * modpow(mint(2), jiyudo);
}

int main() {
    cin >> N >> M;
    fi.clear();
    for (int i = 0; i < M; ++i) {
        int a, b, c; cin >> a >> b >> c; --a, --b;
        fi[pint(a, b)] = c;
    }
    cout << solve() << endl;
}


















Measured memory_bytes: 24832