zoukankan      html  css  js  c++  java
  • BZOJ 2303: [Apio2011]方格染色 [并查集 数学!]

    题意:

    $n*m:n,m le 10^6$的网格,每个$2 imes 2$的方格必须有1个或3个涂成红色,其余涂成蓝色

    有一些方格已经有颜色

    求方案数


    太神了!!!花我三节课

    首先想了一下只有两行,发现可以直接$f[i][3] DP$出来,每一列放的方案只与上一列有关

    如果有多行呢,我们可以把上一列放的状态状压$f[i][s]$,然后枚举转移

    复杂度爆炸

    好,看一眼题解

    woc题解说的些什么东西根本看不懂,还是自己想吧

    发现,貌似一个状态只有两个后继状态唉,就是说这一列的右面一列只有两种放法是合法的

    数学归纳法证一下,两行的情况每种列的放法有两个后继,设n行成立,那么n+1行的下一列选或不选就已经确定了...好像成立唉!

    并且这两个后继还是每个位置都相反的!

    总算看明白题解那句:

    如果确定了第一行,接下来的每一行只会是 1.上一行所有奇数列异或1后得到 2.上一行所有偶数列异或1后得到 (这里把之前的行列倒换了)

    其实可以直观理解,因为要保证是奇性啊

    这样的话,不考虑已经涂色的,方案数就是第一行的方案数*(行数-1)$2^{n+m-1}$了

    考虑涂色!

    首先,每个有涂色的行两个后继状态只有一个合法了

    再考虑这一行的涂色对第一行的影响,如果有一行两个位置$x,y$已经涂色,因为只有那两种变换所以:

    $1. x,y同奇偶,每行都必须同色$

    $2. x,y异奇偶,跟这一行同奇偶的行必须同色,异奇偶的行必须异色$

    用个种类并查集就可以判断无解了!

    方案数?把有关系限制的列连起来,求连通块数就行了 

    注意第一行如果有已经涂色的,颜色就直接确定了而不是同色或者异色,所以包含他们的连通块不能再考虑

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    using namespace std;
    #define pii pair<int, int>
    #define MP make_pair
    #define fir first
    #define sec second
    const int N=1e6+5, P=1e9;
    typedef long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n, m, k, c[N], p, x, y;
    struct meow{int r, c;}t;
    vector<meow> q[N];
    int fa[N];
    int find(int x) {return x==fa[x] ? x : fa[x]=find(fa[x]);}
    struct UFS{
        int fa[N], val[N];
        int find(int x) {
            if(x == fa[x]) return x;
            int root = find(fa[x]);
            val[x] ^= val[fa[x]];
            return fa[x] = root;
        }
        bool Union(int x, int y, int p) {
            int f1 = find(x), f2 = find(y);
            if(f1 != f2) {
                fa[f1] = f2;
                val[f1] = val[x]^val[y]^p;
            } else if((val[x]^val[y]) != p) return false;
            return true;
        }
    }F;
    int fix[N], mark[N];
    int Pow(ll a, int b) {
        ll ans=1;
        for(; b; b>>=1, a=a*a%P) 
            if(b&1) ans=ans*a%P;
        return ans;
    }
    int main() {
        freopen("in","r",stdin);
        n=read(); m=read(); k=read();
        for(int i=1; i<=k; i++) {
            x=read(), t.r=read(), t.c=read(), q[x].push_back(t);
            mark[x] = 1;
            if(x == 1) fix[t.r] = 1;
        }
        for(int i=1; i<=m; i++) fa[i] = F.fa[i] = i;
        for(int i=1; i<=n; i++)
            for(int j=1; j<(int)q[i].size(); j++) {
                int a = q[i][j-1].c, b = q[i][j].c, x=q[i][j-1].r, y=q[i][j].r;
                int f1 = find(x), f2 = find(y);
                fa[f1] = f2;
                if(fix[f1]) fix[f2] = 1;
                int p = a^b; if((x&1) != (y&1)) p ^= (i-1)&1;
                if(!F.Union(x, y, p)) {puts("0"); return 0;}
            }
        int ans = 0;
        for(int i=2; i<=n; i++) ans += !mark[i];
        for(int i=1; i<=m; i++) if(fa[i]==i && !fix[i]) ans++;
        printf("%d
    ", Pow(2, ans));
    }
  • 相关阅读:
    JID 2.0 RC4 发布,高性能的 Java 序列化库
    FBReaderJ 1.6.3 发布,Android 电子书阅读器
    Arquillian 1.0.3.Final 发布,单元测试框架
    JavaScript 的宏扩展 Sweet.js
    Hypertable 0.9.6.5 发布,分布式数据库
    JRuby 1.7.0 发布,默认使用 Ruby 1.9 模式
    httppp 1.4.0 发布,HTTP响应时间监控
    Redis 2.6.0 正式版发布,高性能K/V服务器
    OfficeFloor 2.5.0 发布,IoC 框架
    XWiki 4.3 首个里程碑发布
  • 原文地址:https://www.cnblogs.com/candy99/p/6595028.html
Copyright © 2011-2022 走看看