zoukankan      html  css  js  c++  java
  • P3631 [APIO2011]方格染色

    P3631 APIO2011方格染色

    异或性质+带权并查集维护
    主要是异或性质, 题目要求每个(2ast2)的矩形内异或值为1
    在使用(2ast2)的矩形异或的时候,考虑对于一个矩形,除了最外面一圈,内部的格子都会被异或四次,除了内部和四个顶点的格子会被异或两次,所以可以不考虑(同一个值异或两次等于不异或),只用考虑四个顶点,那么考虑矩形 ((a,b)(a,c)(b,d)(c,d))
    我们可以得到
    在矩形长宽均为偶数的情况 (1 = val_{a,b} igoplus val_{a,c} igoplus val_{b,d} igoplus val_{c,d})
    在矩形长宽均为偶数的情况 (0 = val_{a,b} igoplus val_{a,c} igoplus val_{b,d} igoplus val_{c,d})
    更进一步,对于已知两个顶点的矩形,我们可以知道剩下两个点是否相同。
    那么我们令 (a = 1, b = 1) 来做此题。
    然后枚举 (val_{1, 1}) 的值,就行了。

    取0和取1是相反的状态,直接给K个确定点取反就行了。

    注意:

            if ((!(x[i] & 1)) && (!(y[i] & 1))) {
                k[i] ^= 1;
            }
    

    以上代码是为了统一评判标准。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    
    typedef long long ll;
    const ll MAXN = 1e6+10;
    const ll MOD = 1e9;
    
    ll N, M, K, x[MAXN], y[MAXN], k[MAXN], g[MAXN], fa[MAXN];
    
    ll calc(ll);
    ll find_(ll);
    ll kuaisu(ll, ll);
    
    int main() {
        scanf("%lld%lld%lld", &N, &M, &K);
        ll flag = -1;
        for (ll i = 1; i <= K; i++) {
            scanf("%lld%lld%lld", x+i, y+i, k+i);
            if ((!(x[i] & 1)) && (!(y[i] & 1))) {
                k[i] ^= 1;
            }
            if (x[i] == 1 && y[i] == 1) {
                flag = k[i];
            }
        }
        if (-1 != flag) {
            printf("%lld
    ", calc(flag));
        } else {
        	ll ans = calc(0);
            printf("%lld
    ", (ans + calc(1)) % MOD);
        }
        return 0;
    }
    
    ll calc(ll opt) {
        if (opt == 1) {
            for (ll i = 1; i <= K; i++) if (x[i] > 1 && y[i] > 1) {
                k[i] ^= 1;
            }
        }
        for (ll i = 1; i <= N + M; i++) fa[i] = i, g[i] = 0;
        fa[N+1] = 1;
        for (ll i = 1; i <= K; i++) {
            ll a = x[i], b = y[i], c = k[i];
            if (a != 1 || b != 1) {
                ll fx = find_(a), fy = find_(b+N);
                ll tp = g[a] ^ g[b + N] ^ c;
                if (fx != fy) {
                    fa[fy] = fx;
                    g[fy] = tp;
                } else if (tp) {
                    return 0;
                }
            }
        }
        ll tot = 0;
        for (ll i = 1; i <= N + M; i++) {
            if (i == find_(i)) tot++;
        }
        return kuaisu(2, tot-1) % MOD;
    }
    
    ll kuaisu(ll n, ll tim) {
        ll ret = 1;
        while (tim) {
            if (tim & 1) {
                ret = ret * n % MOD;
            }
            tim >>= 1;
            n = n * n % MOD;
        }
        return ret;
    }
    
    ll find_(ll x) {
        ll q;
        if (fa[x] == x) q = x;
        else {
            q = find_(fa[x]);
            g[x] ^= g[fa[x]];
            fa[x] = q;
        }
        return q;
    }
    
    Yukkuri si te yi te ne
  • 相关阅读:
    POJ2503——Babelfish
    深入理解Spring AOP之二代理对象生成
    怎样让索引仅仅能被一个SQL使用
    Linux下改动Oracle数据库字符集命令
    LeetCode15:3Sum
    【C语言】编写函数实现库函数atoi,把字符串转换成整形
    Scala入门到精通——第二十二节 高级类型 (一)
    J2SE核心开发实战(一)——认识J2SE
    A glance on VDBI
    zookeeper 配置文件说明(zoo.cfg)
  • 原文地址:https://www.cnblogs.com/Gensokyo-Alice/p/13667301.html
Copyright © 2011-2022 走看看