【BZOJ2303】【Apio2011】方格染色 异或方程+并查集
2015-04-16 21:52
399 查看
链接:
#include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/45081583"); }
题解:
首先我们发现对于 ai,ja_{i,j} 有下列式子:ai,j xor ai+1,j xor ai,j+1 xor ai+1,j+1==1a_{i,j} ~xor\ a_{i+1,j} ~xor\ a_{i,j+1} ~xor\ a_{i+1,j+1} == 1
然后推导得到对于 ai,ja_{i,j} 有下列式子:
a1,1 xor a1,j xor ai,1 xor ai,j==!(i,j均为偶数)a_{1,1} ~xor\ a_{1,j} ~xor\ a_{i,1} ~xor\ a_{i,j} == !(i,j均为偶数)
然后显然如果我们先涂上第一行和第一列,剩下的点的染色方案是唯一的。
而这些已经的填涂 (i,j)(i,j) 则成了 (1,j)(1,j) 和 (i,1)(i,1) 这俩点之间的限制,即方程四点异或和确定。
我们可以先枚举 (1,1)(1,1) 是 00 还是 11 ,然后其它的染色作为点之间关系跑并查集。
然后会剩下 xx 个连通块,刨去 11 的一个,则此种对 11 染色的方案(染0或者染1)的答案贡献就是 2x−12^{x-1} 。
实现:
一些定义:一个被提前染色了的点有染色权值为其染的色,而如果这个点横纵坐标皆为偶数,则权值取反。
首先说左上角为 00 时的答案计算:
对于点 (i,j),i>1且j>1(i,j) ,i >1且j>1 则它是 点 ii 和 点j+nj+n 之间的限制,表示这两点之间差异为其染色权值。
【原因:如果权值为1,左上角还是0,那么俩点最终染色必须不一样对吧,反之亦然】
对于其它情况,即点在第一行或第一列上,我们认为这是在表示此点和点 (1,1)(1,1) 的关系,处理方式可以与上一种情况相同(甚至在我的实现下代码也是相同哒,不用特殊考虑!)
【原因:如果权值为1,表示与 (0,0)(0,0) 目前 “0”“0” 的染色不同。】
然后对于左上角是 11 时的答案计算:
我们只需要把所有点的染色权值取反,然后推一下发现正好可以跟上述做相同处理。
也就是直接调用上述流程就可以啦!!
特殊问题:
如果点 (1,1)(1,1) 被染色,那么需要特殊判定上面对 11 的枚举。
代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 1001000 #define mod 1000000000 #define A e[i].x #define B e[i].y+n #define C e[i].z using namespace std; struct Eli { int x,y,z; bool read() { scanf("%d%d%d",&x,&y,&z); if(x==1&&y==1)return 1; if(!((x|y)&1))z^=1; return 0; } }e ; int f[N<<1]; bool g[N<<1]; int find(int x) { if(f[x]==x)return x; find(f[x]); g[x]^=g[f[x]]; return f[x]=f[f[x]]; } long long power(long long x,long long p) { long long ret=1; while(p) { if(p&1)ret=(ret*x)%mod; x=(x*x)%mod,p>>=1; } return ret; } int n,m,p; long long getans() { int i,fa,fb,t; for(i=1;i<=n+m;i++)f[i]=i,g[i]=0; f[n+1]=1; for(i=1;i<=p;i++) { fa=find(A),fb=find(B),t=g[A]^g[B]^C; if(fa!=fb)f[fb]=fa,g[fb]=t; else if(t)return 0; } long long ans=0; if(i>p)for(ans=0,i=1;i<=n+m;i++) if(find(i)==i)ans++; return power(2,ans-1); } bool f1=1,f2=1; long long ans1,ans2; int main() { scanf("%d%d%d",&n,&m,&p); for(int i=1;i<=p;i++) { if(e[i].read()) { if(e[i].z)f1=0; else f2=0; i--,p--; } } if(f1)ans1=getans(); if(f2) { for(int i=1;i<=p;i++) if(e[i].x>1&&e[i].y>1)e[i].z^=1; ans2=getans(); } cout<<(ans1+ans2)%mod<<endl; return 0; }
相关文章推荐
- [杂题 异或 带权并查集] BZOJ2303: [Apio2011]方格染色
- [BZOJ2303][APIO2011]方格染色 异或+并查集
- [BZOJ2303]-[Apio2011]方格染色-并查集+题目性质
- [BZOJ2303][Apio2011]方格染色(数学相关+加权并查集)
- BZOJ2303 APIO2011方格染色(并查集)
- [BZOJ 2303][Apio2011]方格染色:并查集
- [BZOJ]2303: [Apio2011]方格染色 并查集
- BZOJ2303 APIO2011方格染色
- BZOJ 2303: [Apio2011]方格染色 [并查集 数学!]
- BZOJ2303: [Apio2011]方格染色
- bzoj 2303: [Apio2011]方格染色 (并查集)
- BZOJ2303: [Apio2011]方格染色
- BZOJ2303: [Apio2011]方格染色
- BZOJ 2303: [Apio2011]方格染色 并查集神题
- bzoj 2303: [Apio2011]方格染色【并查集】
- BZOJ_2303_[Apio2011]方格染色 _并查集
- bzoj 2303: [Apio2011]方格染色
- BZOJ 2303: [Apio2011]方格染色 题解
- bzoj 2303 Apio2011 方格染色
- [APIO2011]方格染色