题目
题意翻译
给你一个 nn 个点 mm 条边的无向图。
你需要给每个点一个点权,使得每条边连接的两个点点权奇偶不同。点权的值域为 {1,2,3}{1,2,3} 。
请求出方案数对 998244353998244353 取模的结果。
图中没有重边或自环。
题目描述
You are given an undirected unweighted graph consisting of n n vertices and m m edges.
You have to write a number on each vertex of the graph. Each number should be 1 1 , 2 2 or 3 3 . The graph becomes beautiful if for each edge the sum of numbers on vertices connected by this edge is odd.
Calculate the number of possible ways to write numbers 1 1 , 2 2 and 3 3 on vertices so the graph becomes beautiful. Since this number may be large, print it modulo 998244353 998244353 .
Note that you have to write exactly one number on each vertex.
The graph does not have any self-loops or multiple edges.
输入输出格式
输入格式:
The first line contains one integer t t ( 1 \le t \le 3 \cdot 10^5 1≤t≤3⋅10
5
) — the number of tests in the input.
The first line of each test contains two integers n n and m m ( 1 \le n \le 3 \cdot 10^5, 0 \le m \le 3 \cdot 10^5 1≤n≤3⋅10
5
,0≤m≤3⋅10
5
) — the number of vertices and the number of edges, respectively. Next m m lines describe edges: i i -th line contains two integers u_i u
i
, v_i v
i
( 1 \le u_i, v_i \le n; u_i \neq v_i 1≤u
i
,v
i
≤n;u
i
≠v
i
) — indices of vertices connected by i i -th edge.
It is guaranteed that \sum\limits_{i=1}^{t} n \le 3 \cdot 10^5
i=1
∑
t
n≤3⋅10
5
and \sum\limits_{i=1}^{t} m \le 3 \cdot 10^5
i=1
∑
t
m≤3⋅10
5
.
输出格式:
For each test print one line, containing one integer — the number of possible ways to write numbers 1 1 , 2 2 , 3 3 on the vertices of given graph so it becomes beautiful. Since answers may be large, print them modulo 998244353 998244353 .
输入输出样例
输入样例#1: 复制
2
2 1
1 2
4 6
1 2
1 3
1 4
2 3
2 4
3 4
输出样例#1: 复制
4
0
说明
Possible ways to distribute numbers in the first test:
the vertex 1 1 should contain 1 1 , and 2 2 should contain 2 2 ;
the vertex 1 1 should contain 3 3 , and 2 2 should contain 2 2 ;
the vertex 1 1 should contain 2 2 , and 2 2 should contain 1 1 ;
the vertex 1 1 should contain 2 2 , and 2 2 should contain 3 3 .
In the second test there is no way to distribute numbers.
思路
显然黑白染色
对于一个联通块,加入黑色点有x个,白色点有y个,那么当黑色点为奇数时,方案数是2x,当白色点为奇数时,方案数是2y,所以一个联通块的方案数是2x+2y
注意不能用memset
代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
inline int read()
{
char c=getchar(); int n=0; bool f=false;
while (c < '0' || c > '9') { if(c == '-') { f=true; } c=getchar(); }
while (c >= '0' && c<='9') { n=(n << 1) + (n << 3) + (c & 15); c=getchar(); }
return f ? -n : n;
}
const int maxN=300005, maxE=maxN << 1, p=998244353;
inline int power(int x, int y) { int res=1; for(; y; y >>= 1, x=1ll * x * x % p) { if(y & 1) { res=1ll * res * x % p; } } return res; }
int n, m, vis[maxN];
long long x, y;
bool flag;
struct List
{
int len, fst[maxN], nxt[maxE], v[maxE];
inline void reset() { len=0; memset(fst, -1, sizeof(int) * (n + 1)); }
inline void insert(int u, int vv) { v[len]=vv, nxt[len]=fst[u], fst[u]=len++; }
inline void connect(int u, int vv) { insert(u, vv), insert(vv, u); }
} ls;
void dfs(int u, int col)
{
if(vis[u] == -1) { vis[u]=col; } else
{
if(vis[u] != col) { flag=true; } return;
}
if(col) { x++; } else { y++; }
for(int i=ls.fst[u]; ~i; i=ls.nxt[i]) { dfs(ls.v[i], !col); }
}
int solve()
{
long long ans=1;
memset(vis, -1, sizeof(int) * (n + 1));
for(int i=1; i<=n; i++)
{
if(vis[i] == -1)
{
flag=false; x=0; y=0; dfs(i, 0);
if(flag) { return 0; }
ans=ans * (power(2, x) + power(2, y)) % p;
}
}
return ans;
}
int main()
{
for(int tn=read(); tn; tn--) {
n=read(); m=read(); ls.reset();
for(int i=1; i<=m; i++) { ls.connect(read(), read()); }
printf("%d\n", solve());
}
return 0;
}