D. Beautiful Graph
解法:
比赛想到的:
遍历过去分成多个层次,如果第一个是偶数,第二个就是奇数。第一个是奇数,第二个就是偶数。
分两种情况讨论,第一个放奇数,第一个放偶数,放完之后判断会不会成立。答案就是放奇数层的个数2^a * 2^b依次类推。
实际:
缺点:
没有考虑到可以统计所有奇数层的个数,直接2^sum。
先放奇数或者先放偶数没有必要单独讨论,总体上就是2^奇数层结点个数+2^偶数。如果一个情况不成立,显然两个都不成立。
每次放完之后判断成不成立,一定超时,在放的时候判断有没有异或为0的(当前层次数和下一层放的数异或,为0说明冲突(奇数层放了偶数))
最后完全没有考虑到是非连通图,需要n遍DFS,DFS之前判断这个连通块是否被访问
Guan Fang Dai Ma[最近期末考试,实在不想重写一遍了。]
#include<bits/stdc++.h>
using namespace std;
const int N = int(3e5) + 999;
const int MOD = 998244353;
int n,m;
vector<int>g[N];
int p2[N];
int cnt[2];
int col[N];
bool bad;
void dfs(int v,int c)
{
col[v]=c;
++cnt[c];
for(auto to : g[v])
{
if(col[to]==-1)dfs(to,1-c);
if((col[v]^col[to])==0)
{
bad=true;
}
}
}
int main()
{
p2[0]=1;
for(int i=1;i<N;i++)
{
p2[i]=(2*p2[i-1])%MOD;
}
int T;
cin>>T;
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;++i)
g[i].clear();
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d %d",&u,&v);
--u,--v;
g[u].push_back(v);
g[v].push_back(u);
}
int res=1;
for(int i=0;i<n;++i)col[i]=-1;
for(int i=0;i<n;++i)
{
if(col[i]!=-1)continue;
bad=false;
cnt[0]=cnt[1]=0;
dfs(i,0);
if(bad)
{
puts("0");
break;
}
int cur = (p2[cnt[0]]+p2[cnt[1]])%MOD;
res = (res * 1LL * cur)%MOD;
}
if(!bad)printf("%d\n",res);
}
return 0;
}