您的位置:首页 > 其它

BZOJ 2303 方格染色

2016-09-06 23:36 211 查看
首先考虑四个格子异或值为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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: