[BZOJ2303][Apio2011]方格染色

试题描述

Sam和他的妹妹Sara有一个包含n × m个方格的
表格。她们想要将其的每个方格都染成红色或蓝色。
出于个人喜好,他们想要表格中每个2 ×   2的方形区
域都包含奇数个(1 个或 3 个)红色方格。例如,右
图是一个合法的表格染色方案(在打印稿中,深色代
表蓝色,浅色代表红色) 。
可是昨天晚上,有人已经给表格中的一些方格染上了颜色!现在Sam和Sara
非常生气。不过,他们想要知道是否可能给剩下的方格染上颜色,使得整个表格
仍然满足她们的要求。如果可能的话,满足他们要求的染色方案数有多少呢?

输入

输入的第一行包含三个整数n, m和k,分别代表表格的行数、列数和已被染
色的方格数目。
之后的k行描述已被染色的方格。其中第 i行包含三个整数xi, yi和ci,分别
代表第 i 个已被染色的方格的行编号、列编号和颜色。ci为 1 表示方格被染成红
色,ci为 0表示方格被染成蓝色。

输出

输出一个整数,表示可能的染色方案数目 W 模 10^9得到的值。(也就是说,如果 W大于等于10^9,则输出 W被10^9除所得的余数)。

输入示例

  1.  

输出示例

  1.  

数据规模及约定

对于所有的测试数据,2 ≤ n, m ≤ 10^6,0 ≤ k ≤ 10^6,1 ≤ xi ≤ n,1 ≤ yi ≤ m。

题解

这种带上某种限制再染色的题目一般都是先确定第一行,再依次确定2~n行,比如这题。

假设先不考虑事先涂上的格子,红色用1表示,蓝色用0表示。我们可以枚举第一行,接下来第 i 行可以是第 i-1 行的全部奇数位取异或值,其余不变;或是第 i-1 行的全部偶数位取异或值,其余不变。于是每向下处理一行答案数扩大1倍,即 方案数 = 第一行方案数 × 2n-1

现在考虑事先涂上的格子,不考虑无解的情况,不难发现同一行若是有两列(第 a 列和第 b 列)都有涂好颜色的格子,那么第一行的第 a 列于第 b 列的颜色就会有一个制约关系,所以把同行的两列合并成一个连通分量,最后看不含第一行位置的连通块的个数,设这个个数为 t,则 第一行方案数 = 2t. 注意,这时 方案数 = 第一行方案数 × 2没有涂颜色的行数

再特判一下无解的情况,之前提到一个制约关系,现在我们就好好研究一下这个制约关系。(设某一行第 a 列和第 b 列数的相等关系为p,p=1时不等,p=0时相等;第一行第 a 列和第 b 列数的相等关系为q,q=1时不等,q=0时相等)

有如下关系:

1.) a 与 b 奇偶性相同时,q = p;

2.) a 与 b 奇偶性不同时,q = p Xor (行数 - 1)。

用并查集维护2m个点,表示第一行每个数(Ai)等于 1 或 0 的条件,每个连通块表示其中所有条件全部成立。例如,当第 a 列和第 b 列数不同时,把(Aa = 1)与(Ab = 0)加入同一个连通块,同时把(Aa = 0)与(Ab = 1)也加入同一个连通块。最后再看是否有(Ai = 0)与(Ai = 1)在同一个连通块中就行了。

  1. #include <iostream>
  2. #include <cstring>
  3. #include <cstdio>
  4. #include <cmath>
  5. #include <algorithm>
  6. #include <stack>
  7. #include <vector>
  8. #include <queue>
  9. #include <cstdlib>
  10. #include <ctime>
  11. using namespace std;
  12.  
  13. const int BufferSize = 1 << 16;
  14. char buffer[BufferSize], *Head, *tail;
  15. inline char Getchar() {
  16. if(Head == tail) {
  17. int l = fread(buffer, 1, BufferSize, stdin);
  18. tail = (Head = buffer) + l;
  19. }
  20. return *Head++;
  21. }
  22. int read() {
  23. int x = 0, f = 1; char c = Getchar();
  24. while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
  25. while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
  26. return x * f;
  27. }
  28.  
  29. #define maxn 1000010
  30. #define MOD 1000000000
  31. #define LL long long
  32. int n, m, k, last[maxn];
  33.  
  34. int fa[maxn], f2[maxn<<1];
  35. bool val[maxn], line[maxn];
  36. int findset(int x) { return x == fa[x] ? x : fa[x] = findset(fa[x]); }
  37. int findset2(int x) { return x == f2[x] ? x : f2[x] = findset2(f2[x]); }
  38.  
  39. struct Point { int x, y, c; } ps[maxn];
  40.  
  41. int Pow(int a, int b) {
  42. if(!b) return 1;
  43. b--; int t = a;
  44. while(b) {
  45. if(b & 1) a = ((LL)a * t) % MOD;
  46. b >>= 1; t = ((LL)t * t) % MOD;
  47. }
  48. return a;
  49. }
  50.  
  51. bool add(int a, int b, bool c1, bool c2, int x) {
  52. if((a & 1) ^ (b & 1)) c2 ^= (x & 1);
  53. int u = findset2((a << 1) | c1), v = findset2((b << 1) | c2);
  54. if(u != v) f2[v] = u;
  55. c1 ^= 1; c2 ^= 1;
  56. u = findset2((a << 1) | c1); v = findset2((b << 1) | c2);
  57. if(u != v) f2[v] = u;
  58. if(findset2(a << 1) == findset2((a << 1) | 1) || findset2(b << 1) == findset2((b << 1) | 1)) return 1;
  59. return 0;
  60. }
  61.  
  62. int main() {
  63. n = read(); m = read(); k = read();
  64. for(int i = 1; i <= k; i++) {
  65. ps[i].x = read(); ps[i].y = read(); ps[i].c = read();
  66. if(ps[i].x == 1) val[ps[i].y] = 1;
  67. line[ps[i].x] = 1;
  68. }
  69.  
  70. int cnt = m;
  71. for(int i = 1; i <= m; i++) fa[i] = i;
  72. for(int i = 1; i <= (m << 1) + 1; i++) f2[i] = i;
  73. for(int i = 1; i <= k; i++) {
  74. if(last[ps[i].x]) {
  75. int t = last[ps[i].x];
  76. int a = findset(ps[i].y), b = findset(ps[t].y);
  77. if(a != b) {
  78. fa[b] = a;
  79. val[a] |= val[b]; val[b] = 0;
  80. cnt--;
  81. }
  82. if(add(ps[i].y, ps[t].y, ps[i].c, ps[t].c, ps[i].x + 1)) {
  83. puts("0");
  84. return 0;
  85. }
  86. }
  87. last[ps[i].x] = i;
  88. }
  89. for(int i = 1; i <= m; i++) if(val[i]) cnt--;
  90. int tmp = 0;
  91. for(int i = 2; i <= n; i++) if(!line[i]) tmp++;
  92. int ans = Pow(2, cnt + tmp);
  93.  
  94. printf("%d\n", ans);
  95.  
  96. return 0;
  97. }

[BZOJ2303][Apio2011]方格染色的更多相关文章

  1. BZOJ2303 APIO2011方格染色(并查集)

    比较难想到的是将题目中的要求看做异或.那么有ai,j^ai+1,j^ai,j+1^ai+1,j+1=1.瞎化一化可以大胆猜想得到a1,1^a1,j^ai,1^ai,j=(i-1)*(j-1)& ...

  2. BZOJ2303: [Apio2011]方格染色 【并查集】

    Description Sam和他的妹妹Sara有一个包含n × m个方格的表格.她们想要将其的每个方格都染成红色或蓝色.出于个人喜好,他们想要表格中每个2 × 2的方形区域都包含奇数个(1 个或 3 ...

  3. BZOJ2303 [Apio2011]方格染色 并查集

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2303 题意概括 现在有一个N*M矩阵,矩阵上只能填数字0或1 现在矩阵里已经有一些格子被填写了数字 ...

  4. BZOJ2303 APIO2011方格染色

    这题太神了 首先我们可以发现只有当i和j都是偶数时a[1][1]^a[1][j]^a[i][1]^a[i][j]=1才满足情况,其它时都为0 所以我们可以先把i和j都为偶数的地方^1变为0 下面才是最 ...

  5. BZOJ_2303_[Apio2011]方格染色 _并查集

    BZOJ_2303_[Apio2011]方格染色 _并查集 Description Sam和他的妹妹Sara有一个包含n × m个方格的 表格.她们想要将其的每个方格都染成红色或蓝色. 出于个人喜好, ...

  6. bzoj 2303: [Apio2011]方格染色

    传送门 Description Sam和他的妹妹Sara有一个包含n × m个方格的表格.她们想要将其的每个方格都染成红色或蓝色.出于个人喜好,他们想要表格中每个2 × 2的方形区域都包含奇数个(1 ...

  7. 【题解】P3631 [APIO2011]方格染色

    很有意思的一道题,所以单独拿出来了. 完整分享看 这里 题目链接 luogu 题意 有一个包含 \(n \times m\) 个方格的表格.要将其中的每个方格都染成红色或蓝色.表格中每个 \(2 \t ...

  8. BZOJ 2303: [Apio2011]方格染色 题解

    题目大意: 有n*m的方格,中间的数要么是1,要么是0,要求任意2*2的方格中的数异或和为1.已知一部分格子中的数,求合法的填数的方案数. 思路: 由题意得:a[i][j]^a[i][j+1]^a[i ...

  9. BZOJ 2303: [Apio2011]方格染色 [并查集 数学!]

    题意: $n*m:n,m \le 10^6$的网格,每个$2 \times 2$的方格必须有1个或3个涂成红色,其余涂成蓝色 有一些方格已经有颜色 求方案数 太神了!!!花我三节课 首先想了一下只有两 ...

随机推荐

  1. linux中的进程管理

    USER  那个用户启动的进程 PID     该进程的ID号 %CPU   占用的CPU百分比 %MEM   占用的物理内存百分比 VSZ      占用虚拟内存大小 KB RSS      占用实 ...

  2. UIScrollView和UIPageController

    实现代码: // // ViewController.m // UIpageControl // // Created by dllo on 16/3/10. // Copyright © 2016年 ...

  3. Python学习日记

    江林楠学习了一下午后给大家呈现的20分钟速成Python—— 一些基本的语法:1.python无变量声明 直接a = []即可.2.python为对齐语言,用制表符表示语句块的嵌套.3.python语 ...

  4. Win7 下以管理员身份运行批处理文件,切换JDK版本

    Win7下 切换JDK的批处理命令 1. 批处理文件(必须以管理员身份执行)内容如下 @echo off rem --- Base Config 配置JDK的安装目录 --- :init set JA ...

  5. 使用background和background-image对CSS优先级造成影响

    在写一个关于背景图的CSS时候发现一个奇怪的现象, 原图: 如下代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitiona ...

  6. Vijos p1892 树上的最大匹配 树形DP+计数 被卡常我有特殊技巧heheda

    https://vijos.org/p/1892 此题需要手动开栈: <<; //256MB char *p=(char*)malloc(size)+size; __asm__(" ...

  7. Java Filter过滤器的简单总结

    1.Filter的介绍 Filter技术是servlet 2.3新增加的功能.它能够对Servlet容器的请求和响应对象进行检查和修改. Filter本身并不生成请求和响应对象,只是提供过滤功能. F ...

  8. HDU2222 Keywords Search [AC自动机模板]

    Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...

  9. DNS安全浅议、域名A记录(ANAME),MX记录,CNAME记录

    相关学习资料 http://baike.baidu.com/link?url=77B3BYIuVsB3MpK1nOQXI-JbS-AP5MvREzSnnedU7F9_G8l_Kvbkt_O2gKqFw ...

  10. insert 多个values

    INSERT INTO `user_mail_attach` VALUES(, , , , , ), (, , , , , ); 这种比写多条insert语句效率高