1. 程式人生 > >BZOJ_2303_[Apio2011]方格染色 _並查集

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

|| 答案 name int strong print 其中 string 方案

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\n",ans);
}

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