题目大意
有一个包含n × m的表格。
每个方格都染成红色或蓝色。
表格中每个2×2的方形区域都包含奇数个(1 个或 3 个)红色方格。
表格中的一些方格染上了颜色。
是否可能给剩下的方格染上颜色,使得整个表格仍然满足要求。
求染色方案数。
题解
我连判断都不会,还叫我求方案?
我还以为是差分约束系统,结果发现,一个点,与它相关的点不止一个,这就没法构图了是不是?
对于一个点
Ai,jxorAi−1,jxorAi,j−1xorAi−1,j−1=1
又有
Ai,jxorAi,j−1xorAi+1,jxorAi+1,j−1=1
等式两边一起异或一下。
Ai−1,jxorAi−1,j−1xorAi+1,j−1xorAi+1,j=0
按照这种方式类推,可以得到以下结论:
对于一个点,如果横坐标和纵坐标都是偶数,那么
Ai,jxorA1,1xorA1,jxorAi,1=1
否则
Ai,jxorA1,1xorA1,jxorAi,1=0
然后可以发现,如果第一行和第一列确定了,那么整张图就确定了。
这道题就变成了一道影子并查集的题。
先枚举
A1,1
的颜色,然后利用这些点之间的关系合并不同的点集。
最后统计有多少个可以自由选择的并查集。
这里有个地方需要注意:
如果这个点确定了,那么这个点的影子并查集也确定了,所以它的影子并查集就不可以再算一次了。
还有点
A1,1
已经被确定了。
答案就加上
2cnt
。
/**************************************************************
Problem: 2303
User: unicornt
Language: C++
Result: Accepted
Time:408 ms
Memory:49180 kb
****************************************************************/
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int M=1000005;
const int mod=1000000000;
int A[M],B[M],C[M];
int par[M<<2],mark[M<<2];
bool flag[M<<2];
int get(int x){
if(par[x]!=x) par[x]=get(par[x]);
return par[x];
}
int fast_pow(int x){
int b=2,res=1;
while(x){
if(x&1) res=(long long)res*b%mod;
b=(long long)b*b%mod;
x>>=1;
}
return res;
}
int main(){
int n,m,num;
scanf("%d%d%d",&n,&m,&num);
for(int i=0;i<num;i++)
scanf("%d%d%d",&A[i],&B[i],&C[i]);
int ans=0;
for(int col=0;col<2;col++){//col(1,1)
for(int i=1;i<=n+n+m+m;i++)
par[i]=i;
bool f=1;
par[1]=n+n+1;
par[1+n]=n+n+m+1;
for(int i=0;i<num;i++){
int Type=0;
if(A[i]%2==0&&B[i]%2==0) Type=1;
if(Type^col^C[i]){
if(get(A[i])==get(B[i]+n+n)){
f=0;
break;
}
par[get(n+n+B[i]+m)]=get(A[i]);
par[get(A[i]+n)]=get(n+n+B[i]);
}else{
if(get(A[i])==get(B[i]+n+n+m)){
f=0;
break;
}
par[get(A[i]+n)]=get(n+n+B[i]+m);
par[get(A[i])]=get(n+n+B[i]);
}
}
if(!f) continue;
for(int i=1;i<=n+n+m+m;i++)
flag[i]=0;
int cnt=0;
for(int i=1;i<=n;i++){
if(!flag[get(i)]){
flag[get(i)]=1;
flag[get(i+n)]=1;
cnt++;
}
}
for(int i=1;i<=m;i++){
if(!flag[get(n+n+i)]){
flag[get(n+n+i)]=1;
flag[get(n+n+i+m)]=1;
cnt++;
}
}
ans+=fast_pow(cnt-1);
if(ans>=mod) ans-=mod;
}
printf("%d\n",ans);
return 0;
}