Description###

老 C 是个程序员。

作为一个懒惰的程序员,老 C 经常在电脑上玩方块游戏消磨时间。游戏被限定在一个由小方格排成的R行C列网格上

,如果两个小方格有公共的边,就称它们是相邻的,而且有些相邻的小方格之间的公共边比较特殊。特殊的公共边排

列得有很强的规律。首先规定,第1行的前两个小方格之间的边是特殊边。然后,特殊边在水平方向上每4个小方格为

一个周期,在竖直方向上每2个小方格为一个周期。所有的奇数列与下一列之间都有特殊边,且所在行的编号从左到

右奇偶交替。下图所示是一个R = C = 8的网格,蓝色标注的边是特殊边。首先,在第1行,第1列和第2列之间有一条

特殊边。因为竖直方向周期为2,所以所有的奇数行,第1列和第2列之间都有特殊边。因为水平方向周期为4,所以所

有奇数行的第5列和第6列之间也有特殊边,如果网格足够大,所有奇数行的第9列和第10列、第13列和第14列之间都

有特殊边。因为所有的奇数列和下一列之间都有特殊边,所以第3列和第4列、第7列和第8列之间也有特殊边,而所在

行的编号从左到右奇偶交替,所以它们的特殊边在偶数行。如果网格的规模更大,我们可以用同样的方法找出所有的

特殊边。

网格的每个小方格刚好可以放入一个小方块,在游戏的一开始,有些小方格已经放上了小方块,另外的小方格没有放

。老 C 很讨厌下图所示的图形,如果他发现有一些小方块排列成了它讨厌的形状(特殊边的位置也要如图中所示),

就很容易弃疗,即使是经过任意次旋转、翻转后排列成讨厌的形状,老 C 也同样容易弃疗。

为了防止弃疗,老 C 决定趁自己还没有弃疗,赶紧移除一些格子里小方块,使得剩下的小方块不能构成它讨厌的形状

。但是游戏里每移除一个方块都是要花费一些金币的,每个方块需要花费的金币有多有少参差不齐。老 C 当然希望

尽可能少的使用游戏里的金币,但是最少要花费多少金币呢?老 C 懒得思考,就把这个问题交给你了

Input###

第一行有3个正整数C, R, n,表示C列R行的网格中,有n个小方格放了小方块。

接下来n行,每行3个正整数x, y, w,表示在第x列第y行的小方格里放了小方块,移除它需要花费w个金币。保证不会

重复,且都在网格范围内。

1 ≤ C, R, n ≤ 10^5 , 1 ≤ w ≤ 10^4

Output###

输出一行,包含一个整数,表示最少花费的金币数量。

Sample Input###

2 2 4

1 1 5

1 2 6

2 1 7

2 2 8

Sample Output###

5


简要题解##

染色分层+最小割


想法##

观察使老C弃疗的图形



发现它们都由特殊边两边的紫色格子,及一个蓝格子、一个绿格子组成。

由此我们可以给整张图染色



(为了方便我把两个紫格子分别染成紫与深蓝)

我们需要移除一些格子使图中不存在连续的 蓝-紫-深蓝-绿 或 绿-紫-深蓝-蓝

由此可以想到用最小割(有一句话说得好:灵感源于性质的相似性)

最小割即把对点的限制转换到对边的限制上。

开始建图。

S向每个绿格子连边,容量为绿格子的w

每个绿格子向相邻的紫格子与深蓝格子连边,容量为INF

紫格子与相邻深蓝格子互相连边,容量为两个格子w的min (其实这两个相邻的点是一体的,就相当于是一个大点。这两个点中间连边相当于拆大点。)

紫格子与深蓝格子向相邻的蓝格子连边,容量为INF

蓝格子向T连边,容量为蓝格子的w


代码##

这道题A的真是不容易……

一开始懒得写hash表光写个hash,结果那么不幸就被卡上了……

(哎,这是第二次了……之前有一次cf没写hash表被hack了…)

调了好久好久,不开森。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<algorithm>
  4. #include<vector>
  5. #define INF 2000000007
  6. #define P 100999
  7. using namespace std;
  8. typedef long long ll;
  9. const int N = 100007;
  10. struct node{
  11. int v,f;
  12. node *next,*rev;
  13. }pool[N*10],*h[N];
  14. int cnt;
  15. void addedge(int u,int v,int f){
  16. node *p=&pool[++cnt],*q=&pool[++cnt];
  17. p->v=v;p->next=h[u];h[u]=p; p->f=f;p->rev=q;
  18. q->v=u;q->next=h[v];h[v]=q; q->f=0;q->rev=p;
  19. }
  20. int S,T;
  21. int que[N],level[N];
  22. bool bfs(){
  23. int head=0,tail=0,u,v;
  24. for(int i=S;i<=T;i++) level[i]=-1;
  25. level[S]=1; que[tail++]=S;
  26. while(head<tail){
  27. u=que[head++];
  28. for(node *p=h[u];p;p=p->next)
  29. if(p->f && level[v=p->v]==-1){
  30. level[v]=level[u]+1;
  31. que[tail++]=v;
  32. }
  33. if(level[T]!=-1) return true;
  34. }
  35. return false;
  36. }
  37. int find(int u,int f){
  38. int v,s=0,t;
  39. if(u==T) return f;
  40. for(node *p=h[u];p;p=p->next)
  41. if(p->f && s<f && level[v=p->v]==level[u]+1){
  42. t=find(v,min(p->f,f-s));
  43. if(t){
  44. s+=t;
  45. p->f-=t;
  46. p->rev->f+=t;
  47. }
  48. }
  49. if(!s) level[u]=-1;
  50. return s;
  51. }
  52. int dinic(){
  53. int flow=0;
  54. while(bfs()) flow+=find(S,INF);
  55. return flow;
  56. }
  57. int C,R,n;
  58. struct data{
  59. int x,y,w,id;
  60. }d[N];
  61. int hash(int x,int y) {
  62. if(x<=0 || y<=0 || x>R || y>C) return P;
  63. return ((ll)x*N+y)%P;
  64. }
  65. vector<data> hh[P+1];
  66. int check(int c,int x,int y){
  67. if(c==P) return 0;
  68. for(int i=0;i<hh[c].size();i++)
  69. if(hh[c][i].x==x && hh[c][i].y==y) return hh[c][i].id;
  70. return 0;
  71. }
  72. int main()
  73. {
  74. scanf("%d%d%d",&C,&R,&n);
  75. for(int i=1;i<=n;i++){
  76. scanf("%d%d%d",&d[i].y,&d[i].x,&d[i].w);
  77. d[i].id=i;
  78. hh[hash(d[i].x,d[i].y)].push_back(d[i]);
  79. }
  80. //addedge
  81. int t,xx,yy;
  82. S=0; T=n+1;
  83. for(int i=1;i<=n;i++){
  84. xx=d[i].x%2; yy=d[i].y%4;
  85. if((xx==1 && yy==1) || (xx==0 && yy==3)){ //purple
  86. t=check(hash(d[i].x,d[i].y+1),d[i].x,d[i].y+1);
  87. if(t) addedge(i,t,min(d[i].w,d[t].w));
  88. }
  89. else if((xx==1 && yy==2) || (xx==0 && yy==0)){ //dark blue
  90. t=check(hash(d[i].x,d[i].y-1),d[i].x,d[i].y-1);
  91. if(t) addedge(i,t,min(d[i].w,d[t].w));
  92. }
  93. else if((xx==1 && yy==3) || (xx==0 && yy==2)){ //green
  94. addedge(S,i,d[i].w);
  95. t=check(hash(d[i].x+1,d[i].y),d[i].x+1,d[i].y);
  96. if(t) addedge(i,t,INF);
  97. t=check(hash(d[i].x-1,d[i].y),d[i].x-1,d[i].y);
  98. if(t) addedge(i,t,INF);
  99. if(yy==3)
  100. t=check(hash(d[i].x,d[i].y-1),d[i].x,d[i].y-1);
  101. else t=check(hash(d[i].x,d[i].y+1),d[i].x,d[i].y+1);
  102. if(t) addedge(i,t,INF);
  103. }
  104. else{ //blue
  105. addedge(i,T,d[i].w);
  106. t=check(hash(d[i].x+1,d[i].y),d[i].x+1,d[i].y);
  107. if(t) addedge(t,i,INF);
  108. t=check(hash(d[i].x-1,d[i].y),d[i].x-1,d[i].y);
  109. if(t) addedge(t,i,INF);
  110. if(yy==1)
  111. t=check(hash(d[i].x,d[i].y-1),d[i].x,d[i].y-1);
  112. else t=check(hash(d[i].x,d[i].y+1),d[i].x,d[i].y+1);
  113. if(t) addedge(t,i,INF);
  114. }
  115. }
  116. printf("%d\n",dinic());
  117. return 0;
  118. }

[bzoj4823][洛谷P3756][Cqoi2017]老C的方块的更多相关文章

  1. 洛谷$P3756\ [CQOI2017]$老$C$的方块 网络流

    正解:网络流 解题报告: 传送门$QwQ$ 看到不能出现给定的讨厌的图形,简单来说就,特殊边两侧的方格不能同时再连方格. 所以如果出现,就相当于是四种方案?就分别炸四个格子. 然后冷静分析一波之后发现 ...

  2. 洛咕 P3756 [CQOI2017]老C的方块

    四染色,贼好想 一个弃疗图形刚好对应一个红-绿-黄-粉色路线(不要吐槽颜色) 就是裸的最小割,建图傻逼懒得写了 #include<bits/stdc++.h> #define il inl ...

  3. [bzoj4824][洛谷P3757][Cqoi2017]老C的键盘

    Description 老 C 是个程序员. 作为一个优秀的程序员,老 C 拥有一个别具一格的键盘,据说这样可以大幅提升写程序的速度,还能让写出来的程序 在某种神奇力量的驱使之下跑得非常快.小 Q 也 ...

  4. 洛谷 P3757 [CQOI2017]老C的键盘

    题面 luogu 题解 其实就是一颗二叉树 我们假设左儿子小于根,右儿子大于根 考虑树形\(dp\) \(f[u][i]\)表示以\(u\)为根的子树,\(u\)为第\(i\)小 那么考虑子树合并 其 ...

  5. 洛谷P3757 [CQOI2017]老C的键盘

    传送门 首先可以直接把整个序列建成一个完全二叉树的结构,这个应该都看得出来 然后考虑树形dp,以大于为例 设$f[i][j]$表示$i$这个节点在子树中排名第$j$位时的总方案数(因为实际只与相对大小 ...

  6. BZOJ 4823 Luogu P3756 [CQOI2017]老C的方块 (网络流、最小割)

    题目链接 (Luogu) https://www.luogu.org/problem/P3756 (BZOJ) http://lydsy.com/JudgeOnline/problem.php?id= ...

  7. P3756 [CQOI2017]老C的方块

    题目链接 看到网格图+最优化问题,当然要想黑白染色搞网络流.不过这道题显然无法用黑白染色搞定. 仔细观察那四种图形,发现都是蓝线两边一定有两个格子,两个格子旁边一定还有且仅有一个格子.因此我们可以这么 ...

  8. 【BZOJ4823】[CQOI2017]老C的方块(网络流)

    [BZOJ4823][CQOI2017]老C的方块(网络流) 题面 BZOJ 题解 首先还是给棋盘进行黑白染色,然后对于特殊边左右两侧的格子单独拎出来考虑. 为了和其他格子区分,我们把两侧的这两个格子 ...

  9. bzoj4823: [Cqoi2017]老C的方块(最小割)

    4823: [Cqoi2017]老C的方块 题目:传送门 题解: 毒瘤题ORZ.... 太菜了看出来是最小割啥边都不会建...狂%大佬强强强   黑白染色?不!是四个色一起染,四层图跑最小割... 很 ...

随机推荐

  1. H3C保存当前配置--用户图示(console)以上

    <H3C>save         //此种保存只默认保存为Startup.cfg ,系统默认是加载此文件 The current configuration will be writte ...

  2. 【b503】篝火晚会

    Time Limit: 1 second Memory Limit: 50 MB [问题描述] 佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了"小教官" ...

  3. JMeter FTP测试计划

    为了演示测试目的,我们将使用公共可用的FTP位置,可以使用它来测试文件的下载. 您可以使用市场上现有的任何可用的演示FTP位置.我们使用URL下的FTP位置: https://dlptest.com/ ...

  4. 025.MFC_窗口操作

    窗口操作 一.建立名为dialogOp 的mfc 工程 ,添加9个button 和1个check box组件,并按如图修改caption属性. 最大化窗口 双击最大化button,进入dialogOp ...

  5. TDengine 时序数据库的 ADO.Net Core 提供程序 Maikebing.EntityFrameworkCore.Taos

    简介 Entity, Framework, EF, Core, Data, O/RM, entity-framework-core,TDengine Maikebing.Data.Taos 是一个基于 ...

  6. umask 设置

    背景: 有时候需要在linux上从其他人的目录里copy文件过来. 最近遇上的事情很麻烦,就是copy的时候发现很多文件copy不过来,copy一个文件夹时,当前文件把权限修改了,结果子目录的中的还没 ...

  7. Kali之msf简单的漏洞利用

    1.信息收集 靶机的IP地址为:192.168.173.136 利用nmap工具扫描其开放端口.系统等 整理一下目标系统的相关信息 系统版本:Windows server 2003 开放的端口及服务: ...

  8. 用postman验证接口是否可掉通

    1.结合fidder抓包工具 2.打开postman 3.点击Launchpad右边“+” 4.选择postman,url粘贴fidder抓出来的数据 5.Header中粘贴fidder抓出来的KEY ...

  9. lua字符串分割函数[适配中文特殊符号混合]

    lua的官方函数里无字符串分割,起初写了个简单的,随之发现如果是中文.字符串.特殊符号就会出现分割错误的情况,所以就有了这个zsplit. function zsplit(strn, chars) f ...

  10. 让你彻底明白TCP三次握手,四次挥手

    今天我们来讲一下TCP的三次握手和四次挥手,先来张思维导图.  一.TCP是什么 TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流 ...