题意
给一个图,图上的点可以被染成权值为1,2,3
令边权=两个点的点权和,求令边权为奇数的所有方案数%998244353
思路来源
自己写的
题解
首先二分图判定一下,分奇偶层;
奇层染奇数,偶层染偶数;
或奇层染偶数,偶层染奇数。
对于每个连通分量,其方案数为(modpow(2,奇层点数,MOD)+modpow(2,偶层点数,MOD))%MOD
这个modpow是快速幂。
然后整个图的就是所有连通分量的乘积%MOD了。
心得
开始没注意到图不一定是连通图,WA了一发。
再后来e数组60W开小了,又WA一发。
再后来这个n总共是3e5,每次去memset所有,T了五六发……
所以应该就是for循环到n赋初值 这样遭遇T=300000 n=1 m=0的极限样例也不会爆了
或者每次用到哪个的时候才去初始化哪个,最后就是改成这样的
代码还是不规范啊……明明能O(均摊n),非要O(T·n),
改完之后2000msTLE变140msAC,真是令人窒息的操作
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <functional>
const int INF=0x3f3f3f3f;
const int maxn=3e5+10;
const int mod=1e9+7;
const int MOD=998244353;
const double eps=1e-7;
typedef long long ll;
#define vi vector<int>
#define si set<int>
#define pii pair<int,int>
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%I64d",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int cnt,head[maxn],color[maxn],shu;
int t,n,m,pos[maxn],neg[maxn],now;
struct edge
{
int to,nex;
}e[maxn*2];
//可能很多连通分量 最后的答案是各连通分量贡献的乘积
//二分图判定一次
void init(int n)
{
for(int i=0;i<n;++i)
color[i]=0,head[i]=-1;
cnt=0;
shu=1;
}
void add(int u,int v)
{
e[cnt].to=v;
e[cnt].nex=head[u];
head[u]=cnt++;
}
ll modpow(ll x,ll n,ll mod)
{
if(n==0)return 1;
ll res=modpow(x,n/2,mod),ans=res*res;
if(ans>=mod)ans%=mod;
if(n&1)ans=ans*x;
if(ans>=mod)ans%=mod;
return ans;
}
bool judge(int u,int c)
{
color[u]=c;
if(c>0)pos[c]++;
else
{
int p=-c;
neg[p]++;
}
for(int i=head[u];~i;i=e[i].nex)
{
int v=e[i].to;
if(color[v]==c)return 0;//相邻同号
if(color[v]==0&&!judge(v,-c))return 0;
}
return 1;
}
ll solve()
{
ll ans=1;
for(int i=0;i<n;++i)
{
if(color[i]==0)
{
pos[shu]=0;//memset会T!!!
neg[shu]=0;//memset会T!!!
if(!judge(i,shu))return 0;
shu++; //shu-1个连通分量
}
}
rep(i,1,shu-1)
{
ll tmp1=modpow(2,pos[i],MOD);
ll tmp2=modpow(2,neg[i],MOD);
ll q=tmp1+tmp2;
if(q>=MOD)q%=MOD;
ans=ans*q;
if(ans>=MOD)ans%=MOD;
}
return ans;
}
int main()
{
sci(t);
while(t--)
{
sci(n),sci(m);
init(n);
rep(i,0,m-1)
{
int u,v;
sci(u),sci(v);
u--,v--;
add(u,v);
add(v,u);
}
printf("%I64d\n",solve());
}
return 0;
}