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

时间:2023-03-09 06:18:55
Educational Codeforces Round 56 (Rated for Div. 2)  D. Beautiful Graph  (二分图染色)

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;
    }