CodeForces1093D:Beautiful Graph(二分图判定+方案数)

每个点可以赋(1, 2, 3)中的任意一个数,但是必须保证相邻点相加为奇数,所以必定一个奇数挨着一个偶数。

由此联系到染色问题,奇环肯定无法染色。

只要图内任意一个联通块无法染色,则需要输出0。

我们进行一遍染色后得到赋值成奇数的点的个数和赋值成偶数点的个数。

则此联通块内的方案数即2^(奇数点个数)+2^(偶数点个数)。

各个联通块的方案数累乘起来即是最终答案。

注意:联通块内仅有一个点则有3种情况。

#include<cstdio>
#define LL long long
#define MOD 998244353
int n, m, k, tot, ans;
int T;
int Ne[1220000], Fir[1220000], To[1220000];
int fa[1220000];
int num[3];
bool vx[1220000];
int find(int x){
   if(fa[x] == x) return x;
   return fa[x] = find(fa[x]);
}
void add(int x, int y){
     k++; To[k] = y; Ne[k] = Fir[x]; Fir[x] = k;
     k++; To[k] = x; Ne[k] = Fir[y]; Fir[y] = k;
}
void dfs(int u, int f, int l, int r){
    tot++;vx[u] = 1;
    if(l == 1) num[0] = (num[0] * 2) % MOD;
    if(r == 1) num[1] = (num[1] * 2) % MOD;
    for (int i = Fir[u]; i != 0; i = Ne[i])
        if(To[i] != f && !vx[To[i]])
            dfs(To[i], u, 1 - l, 1 - r);
}
int main(){
    scanf("%d", &T);
    while(T--){
        bool v = 0;
        scanf("%d%d", &n, &m);
        k = 0;
        for (int i = 1; i <= n; i++) Fir[i] = 0;
        for (int i = 1; i <= n + n; i++) fa[i] = i, vx[i] = 0;
        for (int i = 1; i <= m; i++){
            int x, y;
            scanf("%d%d", &x, &y);
            add(x, y);
            if(find(x) == find(y)) v = 1;
            fa[find(x)] = find(y + n);
            fa[find(y)] = find(x + n);
        }
        if(v)  printf("0\n");
        else {
            ans = 1;
            for (int i = 1; i <= n; i++){
               if(vx[i]) continue;
               tot = 0;
               num[0] = 1; num[1] = 1;
               dfs(i, 0, 0, 1);
               if(tot == 1) ans = ((LL)ans % MOD * 3) % MOD;
               else ans = ((LL)ans * (num[0] + num[1]) % MOD) % MOD;
            }
            printf("%d\n", ans);
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值