BZOJ 2303: [Apio2011]方格染色 并查集神题
2016-09-27 12:05
417 查看
时空隧道
分析:
感觉做过类似的题,第一行确定了,下面的方案就确定了
这道题是同样的思路:
如果没有格子已经确定了颜色,那么第一行的格子color确定之后,下一行只有两种方案可以选择:
1、奇数列不变,偶数列xor1
2、偶数列不变,奇数列xor1
证明如下:
x y
x 1-y
假设x是奇数列,那么四个格子的和一定为奇数,偶数列不变的证明方法同理
那么如果我们在最上面添加一行第0行,就可以把下面的n行都当做随便填的空行来看,所以方案数就是2^m * 2^n=2^n+m
但是现在有一个很麻烦的问题就是有的格子已经确定了color
那么我们发现每一行的确定的格子改变的只是本行的方案数以及第0行的方案数,所以我们只需要计算出第0行的方案数以及有几个空行即可
假设第0行有cnt个方案数,共有k个空行,那么ans=cnt+k-1(因为我们占用了一个空行来当做0行)
接下来就是最神的部分求cnt了
并查集~\ (≧▽≦) /~
我们考虑在第i行有ab两个格子确定了,如果ab都在奇数列或者都在偶数列,那么第0行的ab经过了i次翻转变成了第i行的ab,ab都是同时翻转,所color[a]^color[b]=c[a]^c[b](color[a]代表第0行的color,c[a]代表第i行的color);
那么如果ab一个是奇数列,一个是偶数列呢?
翻转两次这两个就一定能翻成xor和原来一样的了(很显然….)
所以color[a]^color[b]=c[a]^c[b]^(i%2)
这些关系怎么搞,看起来像是个带偏移量的并查集?
觉得自己脑残到一种境界~(>_<)~
一开始只dis只用ca进行了xor
后来发现没有开longlong
还拍了几次,每次第一组数据就WA
(捂脸)
代码如下:
by >_< NeighThorn
分析:
感觉做过类似的题,第一行确定了,下面的方案就确定了
这道题是同样的思路:
如果没有格子已经确定了颜色,那么第一行的格子color确定之后,下一行只有两种方案可以选择:
1、奇数列不变,偶数列xor1
2、偶数列不变,奇数列xor1
证明如下:
x y
x 1-y
假设x是奇数列,那么四个格子的和一定为奇数,偶数列不变的证明方法同理
那么如果我们在最上面添加一行第0行,就可以把下面的n行都当做随便填的空行来看,所以方案数就是2^m * 2^n=2^n+m
但是现在有一个很麻烦的问题就是有的格子已经确定了color
那么我们发现每一行的确定的格子改变的只是本行的方案数以及第0行的方案数,所以我们只需要计算出第0行的方案数以及有几个空行即可
假设第0行有cnt个方案数,共有k个空行,那么ans=cnt+k-1(因为我们占用了一个空行来当做0行)
接下来就是最神的部分求cnt了
并查集~\ (≧▽≦) /~
我们考虑在第i行有ab两个格子确定了,如果ab都在奇数列或者都在偶数列,那么第0行的ab经过了i次翻转变成了第i行的ab,ab都是同时翻转,所color[a]^color[b]=c[a]^c[b](color[a]代表第0行的color,c[a]代表第i行的color);
那么如果ab一个是奇数列,一个是偶数列呢?
翻转两次这两个就一定能翻成xor和原来一样的了(很显然….)
所以color[a]^color[b]=c[a]^c[b]^(i%2)
这些关系怎么搞,看起来像是个带偏移量的并查集?
觉得自己脑残到一种境界~(>_<)~
一开始只dis只用ca进行了xor
后来发现没有开longlong
还拍了几次,每次第一组数据就WA
(捂脸)
代码如下:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<vector> //by NeighThorn using namespace std; const int maxn=1000000+5,MOD=1000000000; int n,m,k,fa[maxn],dis[maxn],cnt=0; struct M{ int Y,C; M(int a=0,int b=0){ Y=a,C=b; } }; vector<M> X[maxn]; inline int find(int x){ if(x==fa[x]) return x; int fx=find(fa[x]); dis[x]=dis[fa[x]]^dis[x]; return fa[x]=fx; } inline int power(long long a,int b){ long long ans=1; while(b){ if(b&1) ans=ans*a%MOD; a=a*a%MOD,b>>=1; } return ans%MOD; } signed main(void){ scanf("%d%d%d",&n,&m,&k); for(int i=1,x,y,c;i<=k;i++) scanf("%d%d%d",&x,&y,&c),X[x].push_back(M(y,c)); for(int i=1;i<=m;i++) fa[i]=i; for(int i=1;i<=n;i++){ if(X[i].size()==0) cnt++; for(int j=1;j<X[i].size();j++){ int a=X[i][j].Y,b=X[i][j-1].Y,c1=X[i][j].C,c2=X[i][j-1].C,fx=find(a),fy=find(b),d; if((a+b)&1) d=c1^c2^(i%2); else d=c1^c2; if(fx==fy){ if((dis[a]^dis[b])!=d){ puts("0"); exit(0); } } else dis[fx]=(dis[a]^dis[b]^d),fa[fx]=fy; } } for(int i=1;i<=m;i++) if(fa[i]==i) cnt++; cout<<power(2LL,cnt-1)<<endl; return 0; }
by >_< NeighThorn
相关文章推荐
- bzoj 2303: [Apio2011]方格染色 (并查集)
- BZOJ 2303: [Apio2011]方格染色 [并查集 数学!]
- bzoj 2303: [Apio2011]方格染色【并查集】
- BZOJ_2303_[Apio2011]方格染色 _并查集
- [BZOJ 2303][Apio2011]方格染色:并查集
- [BZOJ]2303: [Apio2011]方格染色 并查集
- bzoj 2303 Apio2011 方格染色
- 【bzoj 2303】【Apio2011】方格染色
- BZOJ 2303 [Apio2011]方格染色
- bzoj 2303: [Apio2011]方格染色
- BZOJ 2303: [Apio2011]方格染色 题解
- [BZOJ2303]-[Apio2011]方格染色-并查集+题目性质
- BZOJ2303 APIO2011方格染色(并查集)
- [BZOJ2303][Apio2011]方格染色(数学相关+加权并查集)
- [杂题 异或 带权并查集] BZOJ2303: [Apio2011]方格染色
- 2303: [Apio2011]方格染色
- [BZOJ2303][APIO2011]方格染色 异或+并查集
- 【BZOJ2303】【Apio2011】方格染色 异或方程+并查集
- BZOJ 2303 方格染色
- BZOJ2303: [Apio2011]方格染色