Educational Codeforces Round 56 (Rated for Div. 2) D. Beautiful Graph (二分图染色)

-
题意:有\(n\)个点,\(m\)条边的无向图,可以给每个点赋点权\({1,2,3}\),使得每个点连的奇偶不同,问有多少种方案,答案对\(998244353\)取模.
-
题解:要使得每个点所连的奇偶不同,很明显是二分图染色,那么对于某一个联通块,我们可以对左边的点赋\(2\),右边的点赋\({1,3}\),那么左边的点没有选择,只有一种情况,而右边的点每个点可以有两种情况,如果右边的点数是\(k_2\),那么方案数就是\(2^{k_2}\),如果左边赋\({1,3}\)且点数为\(k_1\),右边赋\(2\),方案数就是\(2^{k_1}\),所以一个联通块的方案数就是\(2^{k_1}+2^{k_2}\).我们可以不考虑点权,直接dfs二分图染色,记录二分图两边的点数,再直接贡献给答案即可.
-
代码:
int t; int n,m; vector<int> v[N]; int color[N]; int g[N]; int cnt[N]; int ans; bool dfs(int x,int c){ color[x]=c; for(auto w:v[x]){ if(!color[w]){ if(!dfs(w,3-c)) return false; } else{ if(color[w]==c) return false; } } cnt[c]++; return true; } int main() { //ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); scanf("%d",&t); g[0]=1; for(int i=1;i<=300010;++i){ g[i]=g[i-1]*2%mod; } while(t--){ scanf("%d %d",&n,&m); ans=1; for(int i=1;i<=n;++i){ color[i]=0; } for(int i=1;i<=m;++i){ int a,b; scanf("%d %d",&a,&b); v[a].pb(b); v[b].pb(a); } bool ok=true; for(int i=1;i<=n;++i){ if(!color[i]){ cnt[1]=cnt[2]=0; if(!dfs(i,1)){ ok=false; break; } else{ ans=(ll)ans*(g[cnt[1]]+g[cnt[2]])%mod; } } } if(ok) printf("%d\n",ans); else printf("0\n"); for(int i=1;i<=n;++i) v[i].clear(); } return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮

浙公网安备 33010602011771号