#include using namespace std; constexpr int mod = 998244353; long long modpow(long long a,long long b) { long long ans = 1; while(b) { if(b & 1) { (ans *= a) %= mod; } (a *= a) %= mod; b /= 2; } return ans; } struct UnionFind { vector par; vector size; vector>cld; UnionFind(int n) { par.resize(n); size.resize(n,1); cld.resize(n); for(int i = 0; i < n; i++) { par[i] = i; cld[i].push_back(i); } } int find(int x) { if(par[x] == x) { return x; } return par[x] = find(par[x]); } bool same(int x, int y) { return find(x) == find(y); } int consize(int x) { return size[find(x)]; } bool unite(int x,int y) { x = find(x); y = find(y); if(x == y) { return false; } if(size[x] > size[y]) { swap(x,y); } par[x] = y; size[y] += size[x]; for(auto i:cld[x]) { cld[y].push_back(i); } return true; } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N,Q; cin >> N >> Q; UnionFind uf(N); vectorr(N,-1); int cnt = N; bool ok = true; vectortmp; for(int i = 0; i < Q; i++) { int f; cin >> f; if(f == 1) { int u,v; cin >> u >> v; u--; v--; tmp.push_back(u); tmp.push_back(v); if(!uf.same(u,v)) { cnt--; if(uf.size[u] < uf.size[v]) { swap(u,v); } if(r[u] == -1) { r[u] = 0; } for(int j:uf.cld[v]) { r[j] = r[u]; } uf.unite(u,v); } else if(r[u] != r[v]) { ok = false; } if(ok) { cout << modpow(2,cnt) << "\n"; } else { cout << 0 << "\n"; } } if(f == 2) { int u,v; cin >> u >> v; u--; v--; tmp.push_back(u); tmp.push_back(v); if(!uf.same(u,v)) { cnt--; if(uf.size[u] < uf.size[v]) { swap(u,v); } if(r[u] == -1) { r[u] = 0; } for(int j:uf.cld[v]) { r[j] = !r[u]; } uf.unite(u,v); } else if(r[u] == r[v]) { ok = false; } if(ok) { cout << modpow(2,cnt) << "\n"; } else { cout << 0 << "\n"; } } if(f == 3) { cnt = N; ok = true; for(int j:tmp) { uf.par[j] = j; uf.size[j] = 1; uf.cld[j].clear(); r[j] = -1; } tmp.clear(); cout << modpow(2,N) << "\n"; } } }