• 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);
    }
    
  • 相关阅读:
    九度OJ 1168:字符串的查找删除 (查找)
    九度OJ 1167:数组排序 (排序)
    九度OJ 1166:迭代求立方根 (迭代)
    九度OJ 1165:字符串匹配 (模式匹配)
    九度OJ 1164:旋转矩阵 (矩阵运算)
    九度OJ 1163:素数 (素数)
    九度OJ 1162:I Wanna Go Home(我想回家) (最短路径)
    九度OJ 1161:Repeater(复制器) (递归)
    九度OJ 1160:放苹果 (DFS)
    Sub-process /usr/bin/dpkg returned an error code (1)错误解决办法
  • 原文地址:https://www.cnblogs.com/suika/p/9021367.html
Copyright © 2020-2023  润新知