~~~题面~~~

题解:

做这题做了好久,,,换了4种建图QAQ

首先我们观察弃疗的形状,可以发现有一个特点,那就是都以一个固定不变的特殊边为中心的,如果我们将特殊边两边的方块分别称为s块和t块,

那么我们可以观察到,s块和t块永远是在中心位置,而其他两块则是紧邻s块和t块,一边一个。

所以我们要考虑将这个图像用一根线串起来,这样跑最小割才能割最小的边,

那么如何做到一条边割几个图形呢?

首先我们观察到一个非st方块本来就可以属于多个图形,因此也会有多条连边,因此我们只需要对每个方块拆点,限制其只能割一次就可以了。

一开始我选择的连图方式是:

以特殊边左边为s块,右边为t块,s连向s块,t块连向t(s块和t块名字来源),s块连向四周的非t块,t块四周的非s块连向它,s块四周的非t块连向t块四周的非s块。

但这样为什么这样不行呢?

我们可以观察到这样一种情况,

可以发现,右边的小圆圈同时处在s块和t块周围,那么由于扮演了两个角色,这就有可能导致右边的s块的流量流到左边的t块里,于是就出现了不合法情况。

…………

遂交换偶行的s块和t块。

可以发现,右边的s块和左边的t块构成了一个不合法图形,那么这是为什么?

显然是上面反过来的t块和s块在勾桥搭线。。。。

那怎么办?

我们再观察一下图形。既然所有图形都是以s块和t块为中心,那么这两块显然是更加稳定的,因此我们不再用其他块作为中转块,而是采用以s块和t块为中转。

即:

s ---> s块周围的块 ----> s块 ---> t块 ---> t块周围的块

经验证,可以满足要求。

我是强行暴力人工分类讨论建图的。。。因此代码很长,建图就有60行。。。。

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define inf 2139062143
#define getchar() *o++
#define AC 200100
#define ac 1700000 char READ[], *o = READ;
int n, x, ans, s, t, addflow, X, Y;
int last[AC], good[AC], have[AC], c[AC], power[AC];
int q[AC], head, tail;
int date[ac], Next[ac], haveflow[ac], Head[AC], tot = ; struct point{
int x, y;
}p[AC]; bool operator < (point a, point b)
{
if(a.x != b.x) return a.x < b.x;
else return a.y < b.y;
} map<point, int> m; inline int read()
{
int x=;char c=getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x=x*+c-'',c=getchar();
return x;
} inline void add(int f, int w, int S)
{
date[++tot] = w, Next[tot] = Head[f], haveflow[tot] = S, Head[f] = tot;
date[++tot] = f, Next[tot] = Head[w],/* haveflow[tot] = 0,*/ Head[w] = tot;
// printf("%d ---> %d %d\n", f, w, S);
} void pre()
{
X = read(), Y = read(), n = read();
s = n * + , t = s + ;
for(R i=;i<=n;i++)
{
p[i].y = read(), p[i].x = read(), power[i] = read();//注意行列是反的!
m[p[i]] = i;//编号
}
} void build()//暴力枚举加边
{
int x, y;
for(R i=;i<=n;i++)//枚举方块,只连出边
{
add(i, n + i, power[i]);//拆点连边
x = p[i].x, y = p[i].y;
if(x % )//按奇偶行分类
{
if(y % )//按奇偶列分类(可能为s or t右)
{//因为2 = 2 * 1, 6 = 2 * 3 .... 所以有余数就说明是s
if(((y + ) / ) % )//有余数所以是s
{//跟旁边的t连上
if(m[(point){x, y + }]) add(i + n, m[(point){x, y + }], inf);
}
else add(i + n, t, inf);//不然就要连向t了
}
else//不然就是s左的 or t
{
if((y / ) % )
{
if(m[(point){x, y + }]) add(i + n, m[(point){x, y + }], inf);//如果有余数说明是t
if(m[(point){x + , y}]) add(i + n, m[(point){x + , y}], inf);
if(m[(point){x - , y}]) add(i + n, m[(point){x - , y}], inf);
}
else//不然属于s周围的
{
if(m[(point){x, y + }]) add(i + n, m[(point){x, y + }], inf);
if(m[(point){x + , y}]) add(i + n, m[(point){x + , y}], inf);
if(m[(point){x - , y}]) add(i + n, m[(point){x - , y}], inf);
add(s, i, inf);//注意s周围的要连s
}
}
}
else //偶行
{
if(y % )//奇列,t or s右
{
if(((y + ) / ) % )//如果有余数说明是s右
{
if(m[(point){x, y - }]) add(i + n, m[(point){x, y - }], inf);
if(m[(point){x + , y}]) add(i + n, m[(point){x + , y}], inf);
if(m[(point){x - , y}]) add(i + n, m[(point){x - , y}], inf);
add(s, i, inf);
}
else
{
if(m[(point){x, y - }]) add(i + n, m[(point){x, y - }], inf);//如果有余数说明是t
if(m[(point){x + , y}]) add(i + n, m[(point){x + , y}], inf);
if(m[(point){x - , y}]) add(i + n, m[(point){x - , y}], inf);
}
}
else//t左 or s
{
if((y / ) % ) add(i + n, t, inf);//如果有余数的话,说明是t左
else//不然就是s
if(m[(point){x, y - }]) add(i + n, m[(point){x, y - }], inf);
}//注意加了n才是出发点
}
}
} void bfs()
{
int x, now;
c[t] = , x = t, q[++tail] = t;
while(head < tail)
{
x = q[++head];
for(R i=Head[x]; i; i=Next[i])
{
now = date[i];
if(haveflow[i^] && !c[now])
{
++have[c[now] = c[x] + ];
q[++tail] = now;
}
}
}
memcpy(good, Head, sizeof(Head));
} inline void aru()
{
while(x != s)
{
haveflow[last[x]] -= addflow;
haveflow[last[x] ^ ] += addflow;
x = date[last[x] ^ ];
}
ans += addflow;
} void isap()
{
int now; bool done;
addflow = inf, x = s;
while(c[s] != )
{
if(x == t) aru(), addflow = inf;
done = false;
for(R i =good[x]; i ;i =Next[i])
{
now = date[i];
if(haveflow[i] && c[now] == c[x] -)
{
addflow = min(addflow, haveflow[i]);
last[now] = i;
good[x] = i;
done = true;
x = now;
break;
}
}
if(!done)
{
int go = ;
for(R i=Head[x]; i ;i=Next[i])
{
now = date[i];
if(haveflow[i] && c[now]) go = min(go, c[now]);
}
good[x] = Head[x];
if(!(--have[c[x]])) break;
++have[c[x] = go + ];
if(x != s) x = date[last[x] ^ ];
}
}
printf("%d\n", ans);
} int main()
{
// freopen("in.in","r",stdin);
fread(READ, , , stdin);
pre();
build();
bfs();
isap();
// fclose(stdin);
return ;
}

[CQOI2017]老C的方块 网络流的更多相关文章

  1. BZOJ 4823 [Cqoi2017]老C的方块 ——网络流

    lrd的题解:http://www.cnblogs.com/liu-runda/p/6695139.html 我还是太菜了.以后遇到这种题目应该分析分析性质的. 网络流复杂度真是$O(玄学)$ #in ...

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

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

  3. bzoj 4823 [Cqoi2017]老C的方块——网络流

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4823 一个不合法方案其实就是蓝线的两边格子一定选.剩下两部分四相邻格子里各选一个. 所以这个 ...

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

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

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

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

  6. bzoj 4823: [Cqoi2017]老C的方块 [最小割]

    4823: [Cqoi2017]老C的方块 题意: 鬼畜方块游戏不解释... 有些特殊边,有些四个方块组成的图形,方块有代价,删掉一些方块使得没有图形,最小化代价. 比较明显的最小割,一个图形中必须删 ...

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

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

  8. 【题解】CQOI2017老C的方块

    网络流真的是一种神奇的算法.在一张图上面求感觉高度自动化的方案一般而言好像都是网络流的主阵地.讲真一开始看到这道题也有点懵,题面很长,感觉很难的样子.不过,仔细阅读了题意之后明白了:我们所要做的就是要 ...

  9. BZOJ 4823: [Cqoi2017]老C的方块

    分析: 我觉得我的网络流白学了...QAQ... 其实数据范围本是无法用网络流跑过去的,然而出题者想让他跑过去,也就跑过去了... 看到题目其实感觉很麻烦,不知道从哪里入手,那么仔细观察所给出的有用信 ...

随机推荐

  1. MySQL高级-MySQL安装

    1.mysql安装 检查系统是否安装过mysql 查询命令:rpm -qa|grep -i mysql 删除命令:rpm -e RPM软件包名(该名字是上一个命令查出来的名字) 安装命令:rpm -i ...

  2. Redis系列六 Redis事务

    Redis事务 1.介绍 在Redis事务中可以一次执行多个命令,本质是一组命令的集合.一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞. 2.事务的作用 一个队列中, ...

  3. 使用CRF做命名实体识别(三)

    摘要 本文主要是对近期做的命名实体识别做一个总结,会给出构造一个特征的大概思路,以及对比所有构造的特征对结构的影响.先给出我最近做出来的特征对比: 目录 整体操作流程 特征的构造思路 用CRF++训练 ...

  4. photoshop cc 2018安装破解教程(破解补丁,亲测,绝对可用)

    破解步骤说明:下载地址百度网盘,https://pan.baidu.com/s/1cWtpUesl2fms3tFwEC0MiQ 1.右键解压Adobe Photoshop CC 2018 64位这个文 ...

  5. Android Studio|IntelliJ IDEA 常用快捷键(Mac|Window)

    一 For Mac(Mac OS X 10.5+) F1 显示注释文档F2 高亮错误或警告快速定位Command + F12 显示当前文件的结构(查看所有方法)Command + F 查找文本Comm ...

  6. Python字符串所有操作函数

    name = "my \tname is {name} and i am {year} old" print(name.capitalize())#首字母大写 print(name ...

  7. 《javascript模式--by Stoyan Stefanov》书摘--字面量和构造函数

    二.字面量和构造函数 1,能够使用对象字面量时,就没理由使用new Object构造函数 // 一个空对象var 0 = new Object();console.log( o.constructor ...

  8. Python的top-level脚本为什么在磁盘上没有对应的字节码?

    在Python中,如果你使用python script.py这样的方式运行Python脚本,那么script.py就被称为top-level脚本.对于Python来说,这个脚本的字节码是不会写入到磁盘 ...

  9. 20162328蔡文琛week02

    学号 20162328 <程序设计与数据结构>第2周学习总结 教材学习内容总结 这周学习了课本中的第二章内容,比起第一章,本章难度有略微底稿,从刚开始的显示字符转变为简单的加减乘除运算,经 ...

  10. 第一章 Java Web应用开发技术

    Java Web应用开发是基于JavaEE(JavaEnterprise Edition)框架的,而JavaEE是建立在Java平台上的企业级应用解决方案.JavaEES框架提供的Web开发技术主要支 ...