BZOJ2303: [Apio2011]方格染色
2017-09-05 00:17
309 查看
2303: [Apio2011]方格染色
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1927 Solved: 744
[Submit][Status][Discuss]
Description
Sam和他的妹妹Sara有一个包含n × m个方格的表格。她们想要将其的每个方格都染成红色或蓝色。
出于个人喜好,他们想要表格中每个2 × 2的方形区
域都包含奇数个(1 个或 3 个)红色方格。例如,右
图是一个合法的表格染色方案(在打印稿中,深色代
表蓝色,浅色代表红色) 。
可是昨天晚上,有人已经给表格中的一些方格染上了颜色!现在Sam和Sara
非常生气。不过,他们想要知道是否可能给剩下的方格染上颜色,使得整个表格
仍然满足她们的要求。如果可能的话,满足他们要求的染色方案数有多少呢?
Input
输入的第一行包含三个整数n, m和k,分别代表表格的行数、列数和已被染色的方格数目。
之后的k行描述已被染色的方格。其中第 i行包含三个整数xi, yi和ci,分别
代表第 i 个已被染色的方格的行编号、列编号和颜色。ci为 1 表示方格被染成红
色,ci为 0表示方格被染成蓝色。
Output
输出一个整数,表示可能的染色方案数目 W 模 10^9得到的值。(也就是说,如果 W大于等于10^9,则输出 W被10^9除所得的余数)。对于所有的测试数据,2 ≤ n, m ≤ 106
,0 ≤ k ≤ 10^6
,1 ≤ xi ≤ n,1 ≤ yi ≤ m。
Sample Input
3 4 32 2 1
1 2 0
2 3 1
Sample Output
8HINT
数据为国内数据+国际数据+修正版鸣谢GYZ
Source
【题解】最近总是犯一些蠢到极点的错误。
不(非常)难得到g[1][1] ^ g[i][1] ^ g[1][j] ^ g[i][j] = [i mod 2 == 0 && j mod 2 == 0]
不(非常)难发现确定了第一列和第一行就确定了整个表格
于是我们可以枚举g]1][1]的状态,通过已知g[i][j]来判断g[1][j]和g[i][1]是否相等,这样形成了
若干组有且仅有两个选项的约束关系(自己与自己绑在一组也是),答案就是2^(num-1),因为1已经确定了
用加权并查集来维护某个元素与其父亲节点是否相等,0为相等,1为不等
合并时先find两个元素,使之在两代表元素的下面,然后根据关系合并
相等^相等=相等
不等^不等=相等
相等^不等=不等
是很好用的性质
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <vector> #define max(a, b) ((a) > (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) inline void read(long long &x) { x = 0;char ch = getchar(), c = ch; while(ch < '0' || ch > '9')c = ch, ch = getchar(); while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar(); if(c == '-')x = -x; } const long long MAXN = 1000000 + 10; const long long MAXM = 1000000 + 10; const long long MAXK = 1000000 + 10; const long long MOD = 1000000000; long long n,m,ans1,ans2,k; long long x[MAXK], y[MAXK], color[MAXK]; long long fa[MAXK << 1], w[MAXK << 1], ok; //0相等,1不等 long long find(long long x) { if(x == fa[x])return x; int f = find(fa[x]); w[x] ^= w[fa[x]]; fa[x] = f; return f; } long long pow(long long a, long long b) { long long r = 1, base = a % MOD; for(;b;b >>= 1) { if(b & 1) r *= base, r %= MOD; base *= base, base %= MOD; } return r % MOD; } long long solution() { for(register long long i = n + m + 10;i >= 1;-- i)fa[i] = i, w[i] = 0; fa[n + 1] = 1; register long long tmp,f1,f2,now = 0,a; for(register long long i = 1;i <= k;++ i) { if(x[i] == 1 && y[i] == 1)continue; if((x[i] & 1) || (y[i] & 1)) tmp = 0; else tmp = 1; tmp ^= (0 ^ color[i]); f1 = find(x[i]), f2 = find(y[i] + n); a = w[x[i]] ^ w[y[i] + n] ^ tmp; if(f1 == f2 && a)return 0; fa[f2] = f1, w[f2] = a; } for(register long long i = n + m;i >= 1;-- i) if(fa[i] == i)++ now; return pow(2, now - 1); } int main() { read(n), read(m), read(k); for(register long long i = 1;i <= k;++ i) { read(x[i]), read(y[i]), read(color[i]); if(x[i] == 1 && y[i] == 1) if(!color[i]) ok = 1; else ok = 2; } ans1 = solution(); for(register long long i = 1;i <= k;++ i) color[i] ^= 1; ans2 = solution(); if(ok == 1) ans2 = 0; if(ok == 2) ans1 = 0; printf("%lld", (ans1 + ans2) % MOD); return 0; }
BZOJ2303
相关文章推荐
- [杂题 异或 带权并查集] BZOJ2303: [Apio2011]方格染色
- [BZOJ2303]-[Apio2011]方格染色-并查集+题目性质
- 【BZOJ2303】【Apio2011】方格染色 异或方程+并查集
- BZOJ2303 APIO2011方格染色
- BZOJ2303: [Apio2011]方格染色
- BZOJ2303 APIO2011方格染色(并查集)
- [BZOJ2303][Apio2011]方格染色(数学相关+加权并查集)
- BZOJ2303: [Apio2011]方格染色
- [BZOJ2303][APIO2011]方格染色 异或+并查集
- BZOJ_2303_[Apio2011]方格染色 _并查集
- [Apio2011]方格染色
- [Apio2011]方格染色
- [BZOJ]2303: [Apio2011]方格染色 并查集
- bzoj 2303 Apio2011 方格染色
- 2303: [Apio2011]方格染色
- bzoj 2303: [Apio2011]方格染色
- BZOJ 2303: [Apio2011]方格染色 题解
- BZOJ 2303: [Apio2011]方格染色 并查集神题
- 【bzoj 2303】【Apio2011】方格染色
- BZOJ 2303: [Apio2011]方格染色 [并查集 数学!]