题目:http://codeforces.com/contest/1093/problem/D
题意:给你一张图,每个点可以填1,2,3 问有多少中填法使得任意两个相邻顶点和为奇数
思路:
第一个点我们填奇数的话有两种 1或3,那么下一个点只能填2,第三个点两种方法… 找到规律,奇数点x,那么方案数为2^x
第一个点填偶数 第二点两种方法 第三个点一种…
偶数点y 方案数2^y
总的方案数为从一个点出发找到奇数点x和偶数点y
2^x + 2^y
我们每搜过一个点,标记该点的奇偶,如果第二次搜到这个点与邻近点奇偶形同说明有奇数环,那么就无解,
注意:这个图可能不是所有点都是连通的,所以要把每个点都搜一遍,答案乘起来
#include<bits/stdc++.h>
#define fi first
#define se second
#define FOR(a) for(int i=0;i<a;i++)
#define sc(a) scanf("%d",&a)
#define show(a) cout<<a<<endl;
#define show2(a,b) cout<<a<<" "<<b<<endl;
#define show3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl;
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<P, int> LP;
const ll inf = 1e17 + 10;
const int N = 3e5 + 10;
const ll mod = 998244353;
map<string, int>ml;
ll b[N], vis[N], po[N],num[N], t, n, m, x, y, k, a[N];
ll ex, ey, cnt, ans, sum, flag;
ll dist[N];
ll dp[N];
deque <int> q;
vector<int> v[N];
void dfs(int u,int cnt)
{
if(flag) return ;
if(cnt==1) x++;
if(cnt==2) y++;
vis[u]=cnt;
//show2(u,cnt);
//show2('x',x);
//show2('y',y);
for(int i=0;i<v[u].size();i++)
{
int to=v[u][i];
if(vis[to]==0)
{
dfs(to,3-cnt);
}
else if(vis[to]==cnt)
{
flag=1;
return;
}
}
}
int main()
{
ios::sync_with_stdio ( false );
cin.tie ( 0 );
cin>>t;
po[0]=1;
for(int i=1;i<=N;i++)
po[i]=(po[i-1]*2)%mod;
while(t--)
{
cin>>n>>m;
flag=0;
ans=1;
for(int i=1;i<=m;i++)
{
cin>>x>>y;
v[y].push_back(x);
v[x].push_back(y);
}
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
x=0;
y=0;
dfs(i,1);
ans=ans*(po[x]+po[y])%mod;
}
}
for(int i=1;i<=n;i++)
{
v[i].clear();
vis[i]=0;
}
if(flag)
{
cout<<0<<endl;
}
else cout<<ans<<endl;
}
}