https://codeforces.com/contest/1093/problem/D
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define pb push_back
#define mp make_pair
#define IO ios::sync_with_stdio(false)
#define fi first
#define se second
typedef long long ll;
typedef pair<ll,ll> pll;
const int maxn=3e5+5;
const ll INF=0x3f3f3f3f;
const ll mod=998244353;
const double PI=acos(-1.0);
int n,m,k,t,T,minn=INF,maxx,sum,tmp,f,ans;
int u,v,black,white;
//二分图匹配 方案数
int color[maxn],p[maxn];//颜色 位置
struct node{
int to,nxt; //邻接表
}edge[maxn<<1];//无向边
void addedge(int x,int y)
{
t++;
edge[t].to=y;
edge[t].nxt=p[x];//下一个连x nxt表示位置
p[x]=t;//u的实际位置在cnt
}
void dfs(int k,int c) //k第几个点
{
if (f==0) return;
//计数
color[now]=c;//染色 c==0白色
if (c==0) white++;else black++;
for (int i=p[k];i;i=edge[i].nxt)//当前点
{
if (f==0) return;
if (color[edge[i].to]==-1) //下一个点
dfs(edge[i].to,c^1); //相邻两点染不同颜色 2 1/3 任意一条边的点权和为奇数
else if (color[edge[i].to]==c) //已被染成与当前点相同颜色 不是二分图
{
f=0;return;
}
}
}
ll ksm(ll a,ll b){
ll res=1;
while(b){
if(b&1){
res=res*a%mod;
}
a=a*a%mod;
b>>=1;
}
return res;
}
int main(){
IO;
cin>>T;
while(T--){
cin>>n>>m;
for(int i=1;i<=n;i++) p[i]=0,color[i]=-1; //位置还未被初始化 颜色未染 防止memset 0较少 TLE
f=1;
ans=1;
t=0; //邻接表重建
for(int i=1;i<=m;i++){
cin>>u>>v;
addedge(u,v); addedge(v,u);
}
for(int i=1;i<=n;i++){
if(color[i]==-1){//任一点开始dfs
black=0,white=0;
dfs(i,0); //数颜色 分两类 2 1/3 求和奇数
//所有白点染成2 黑点染成1/3
//所有黑点染成2 白点染成1/3
ans=ans*(ksm(2,black)+ksm(2,white))%mod;
}
}
if(f==0)
ans=0;
cout<<ans<<endl;
}
return 0;
}