首先考虑四个格子异或值为1。
然后(重点)发现每个格子的值只和最上面,最左边,和(1,1)的格子的颜色有关。
枚举(1,1)的颜色,联立方程,可以将未知数减少,那么并查集可做。
最后算答案的时候,有些连通块颜色确定,有些不确定,不确定的*2即可。
这题要注意细节!其实一开始的思路最不好想。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 1000500 #define mod 1000000000 using namespace std; struct pnt { int x,y,c; }p[maxn]; int n,m,k,fath[maxn<<1],dis[maxn<<1],val[maxn<<1],flag=-1,cnt[maxn<<1]; void reset() { for (int i=1;i<=(n-1)+(m-1);i++) { fath[i]=i; dis[i]=0; val[i]=-1; cnt[i]=0; } } int getfather(int x) { if (x==fath[x]) return fath[x]; if (val[x]!=-1) { if ((val[fath[x]]!=-1) && (val[fath[x]]!=(val[x]^dis[x]))) return -1; val[fath[x]]=val[x]^dis[x]; } int ret=getfather(fath[x]); dis[x]^=dis[fath[x]]; fath[x]=ret; return fath[x]; } int f_pow(int a,int b) { int base=a,ans=1; while (b) { if (b&1) ans=(ans*base)%mod; base=(base*base)%mod; b>>=1; } return ans%mod; } int gets(int r) { int ans=1; if (flag==1-r) return 0; reset(); for (int i=1;i<=k;i++) { if ((p[i].x==1) && (p[i].y==1)) { if (p[i].c!=r) return 0; } else if ((p[i].x==1) && (p[i].y!=1)) {if ((val[n+p[i].y-2]!=p[i].c) && (val[n+p[i].y-2]!=-1)) return 0;val[n+p[i].y-2]=p[i].c;} else if ((p[i].x!=1) && (p[i].y==1)) {if ((val[p[i].x-1]!=p[i].c) && (val[p[i].x-1]!=-1)) return 0;val[p[i].x-1]=p[i].c;} else { int x=p[i].x-1,y=n+p[i].y-2; int f1=getfather(x),f2=getfather(y); if ((f1==-1) || (f2==-1)) return 0; if (f1==f2) { int ret=dis[x]^dis[y]^r; if ((p[i].x%2==0) && (p[i].y%2==0)) ret^=1; if (ret!=p[i].c) return 0; } else { int ret=p[i].c^dis[x]^dis[y]^r; if ((p[i].x%2==0) && (p[i].y%2==0)) ret^=1; if ((val[f1]!=-1) && (val[f2]!=-1)) { if ((val[f1]^ret)!=val[f2]) return 0; } else if ((val[f1]==-1) && (val[f2]!=-1)) {fath[f1]=f2;dis[f1]=ret;} else if ((val[f1]!=-1) && (val[f2]==-1)) {fath[f1]=f2;dis[f1]=ret;val[f2]=val[f1]^ret;} else {fath[f1]=f2;dis[f1]=ret;} } } } for (int i=1;i<=(n-1)+(m-1);i++) { int ret=getfather(i); if (ret==-1) return 0; cnt[ret]++; } for (int i=1;i<=(n-1)+(m-1);i++) { if ((fath[i]==i) && (val[i]==-1)) ans=(ans*2)%mod; } return ans%mod; } int main() { scanf("%d%d%d",&n,&m,&k); for (int i=1;i<=k;i++) { scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].c); if ((p[i].x==1) && (p[i].y==1)) flag=p[i].c; } printf("%d\n",(gets(0)+gets(1))%mod); return 0; }