首页 > 代码库 > BZOJ 2303 方格染色

BZOJ 2303 方格染色

首先考虑四个格子异或值为1。

然后(重点)发现每个格子的值只和最上面,最左边,和(1,1)的格子的颜色有关。

枚举(1,1)的颜色,联立方程,可以将未知数减少,那么并查集可做。

最后算答案的时候,有些连通块颜色确定,有些不确定,不确定的*2即可。

这题要注意细节!其实一开始的思路最不好想。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define maxn 1000500#define mod 1000000000using 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;}

 

BZOJ 2303 方格染色