zoukankan      html  css  js  c++  java
  • BZOJ_2303_[Apio2011]方格染色 _并查集

    BZOJ_2303_[Apio2011]方格染色 _并查集

    Description

    Sam和他的妹妹Sara有一个包含n × m个方格的
    表格。她们想要将其的每个方格都染成红色或蓝色。
    出于个人喜好,他们想要表格中每个2 ×   2的方形区
    域都包含奇数个(1 个或 3 个)红色方格。例如,右
    图是一个合法的表格染色方案(在打印稿中,深色代
    表蓝色,浅色代表红色) 。
    可是昨天晚上,有人已经给表格中的一些方格染上了颜色!现在Sam和Sara
    非常生气。不过,他们想要知道是否可能给剩下的方格染上颜色,使得整个表格
    仍然满足她们的要求。如果可能的话,满足他们要求的染色方案数有多少呢?


    Input

    输入的第一行包含三个整数n, m和k,分别代表表格的行数、列数和已被染
    色的方格数目。
    之后的k行描述已被染色的方格。其中第 i行包含三个整数xi, yi和ci,分别
    代表第 i 个已被染色的方格的行编号、列编号和颜色。ci为 1 表示方格被染成红
    色,ci为 0表示方格被染成蓝色。

    Output

    输出一个整数,表示可能的染色方案数目 W 模 10^9得到的值。(也就是说,如果 W大于等于10^9,则输出 W被10^9除所得的余数)。

    对于所有的测试数据,2 ≤ n, m ≤ 106
    ,0 ≤ k ≤ 10^6
    ,1 ≤ xi ≤ n,1 ≤ yi ≤ m。

    Sample Input

    3 4 3
    2 2 1
    1 2 0
    2 3 1

    Sample Output

    8

    对于(i,j)有a[i][j]^a[i+1][j]^a[i][j+1]^a[i+1][j+1]=1
    从(1,1)到(i-1,j-1)的这个式子全都异或起来。
    得到a[1][1]^a[1][j]^a[i][1]^a[i][j]=[i%2==0&&j%2==0]。
    即确定了第一行和第一列的颜色就确定了整个方格的颜色。
    于是枚举(1,1)的颜色,对于每个(x,y,c),把a[1][y]和a[x][1]用并查集连起来。
    有环则无解,否则答案等于二的连通块个数-1次方。
     
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    #define N 2000050
    inline char nc() {
        static char buf[100000],*p1,*p2;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int rd() {
        register int x=0;
        register char s=nc();
        while(s<'0'||s>'9') s=nc();
        while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+s-'0',s=nc();
        return x;
    }
    int fa[N],n,m,a[N],k,xx[N],yy[N],cc[N];
    ll mod=1000000000;
    ll qp(ll x,ll y) {ll re=1; for(;y;y>>=1ll,x=x*x%mod) if(y&1ll) re=re*x%mod; return re;}
    int find(int x) {
        if(fa[x]==x) return x;
        int tmp=find(fa[x]);
        a[x]^=a[fa[x]];
        return fa[x]=tmp;
    }
    int main() {
        n=rd(); m=rd(); k=rd();
        register int i;
        for(i=1;i<=k;i++) {
            xx[i]=rd(); yy[i]=rd(); cc[i]=rd();
        }
        int col1,flg[2];
        flg[0]=flg[1]=0;
        ll ans=0;
        for(col1=0;col1<2;col1++) {
            int cnt=0;
            for(i=1;i<=n+m-1;i++) fa[i]=i,a[i]=0;
            for(i=1;i<=k;i++) {
                int p=col1^cc[i]^(xx[i]%2==0&&yy[i]%2==0);
                int x=xx[i],y=yy[i]+n-1;
                int dx=find(x),dy=find(y);
                if(dx!=dy) {
                    fa[dx]=dy;
                    a[dx]=a[y]^a[x]^p;
                }else {
                    if((a[x]^a[y])!=p) {
                        flg[col1]=1; break;
                    }
                }
            }
            for(i=1;i<=n+m-1;i++) {
                if(fa[i]==i) {
                    cnt++;
                }
            }
            cnt--;
            if(!flg[col1]) {
                ans=(ans+qp(2,cnt))%mod;
            }
        }
        printf("%lld
    ",ans);
    }
    
  • 相关阅读:
    How to change hostname on SLE
    How to install starDIct on suse OS?
    python logging usage
    How to reset password for unknow root
    How to use wget ?
    How to only capute sub-matched character by grep
    How to inspect who is caller of func and who is the class of instance
    How to use groovy script on jenkins
    Vim ide for shell development
    linux高性能服务器编程 (二) --IP协议详解
  • 原文地址:https://www.cnblogs.com/suika/p/9021367.html
Copyright © 2011-2022 走看看