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

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

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

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

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

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

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

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

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

 

你可能感兴趣的:(CodeForces)