Educational Codeforces Round 56 (Rated for Div. 2) D. Beautiful Graph (二分圖染色)
阿新 • • 發佈:2020-07-31
-
題意:有\(n\)個點,\(m\)條邊的無向圖,可以給每個點賦點權\({1,2,3}\),使得每個點連的奇偶不同,問有多少種方案,答案對\(998244353\)取模.
-
題解:要使得每個點所連的奇偶不同,很明顯是二分圖染色,那麼對於某一個聯通塊,我們可以對左邊的點賦\(2\),右邊的點賦\({1,3}\),那麼左邊的點沒有選擇,只有一種情況,而右邊的點每個點可以有兩種情況,如果右邊的點數是\(k2\),那麼方案數就是\(2^k2\),如果左邊賦\({1,3}\)且點數為\(k1\),右邊賦\(2\),方案數就是\(2^k1\),所以一個聯通塊的方案數就是\(2^k1+2^k2\).我們可以不考慮點權,直接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; }