[CQOI2017]老C的方块 网络流
题解:
做这题做了好久,,,换了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的方块 网络流的更多相关文章
- BZOJ 4823 [Cqoi2017]老C的方块 ——网络流
lrd的题解:http://www.cnblogs.com/liu-runda/p/6695139.html 我还是太菜了.以后遇到这种题目应该分析分析性质的. 网络流复杂度真是$O(玄学)$ #in ...
- 洛谷$P3756\ [CQOI2017]$老$C$的方块 网络流
正解:网络流 解题报告: 传送门$QwQ$ 看到不能出现给定的讨厌的图形,简单来说就,特殊边两侧的方格不能同时再连方格. 所以如果出现,就相当于是四种方案?就分别炸四个格子. 然后冷静分析一波之后发现 ...
- bzoj 4823 [Cqoi2017]老C的方块——网络流
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4823 一个不合法方案其实就是蓝线的两边格子一定选.剩下两部分四相邻格子里各选一个. 所以这个 ...
- BZOJ 4823 Luogu P3756 [CQOI2017]老C的方块 (网络流、最小割)
题目链接 (Luogu) https://www.luogu.org/problem/P3756 (BZOJ) http://lydsy.com/JudgeOnline/problem.php?id= ...
- 【BZOJ4823】[CQOI2017]老C的方块(网络流)
[BZOJ4823][CQOI2017]老C的方块(网络流) 题面 BZOJ 题解 首先还是给棋盘进行黑白染色,然后对于特殊边左右两侧的格子单独拎出来考虑. 为了和其他格子区分,我们把两侧的这两个格子 ...
- bzoj 4823: [Cqoi2017]老C的方块 [最小割]
4823: [Cqoi2017]老C的方块 题意: 鬼畜方块游戏不解释... 有些特殊边,有些四个方块组成的图形,方块有代价,删掉一些方块使得没有图形,最小化代价. 比较明显的最小割,一个图形中必须删 ...
- bzoj4823: [Cqoi2017]老C的方块(最小割)
4823: [Cqoi2017]老C的方块 题目:传送门 题解: 毒瘤题ORZ.... 太菜了看出来是最小割啥边都不会建...狂%大佬强强强 黑白染色?不!是四个色一起染,四层图跑最小割... 很 ...
- 【题解】CQOI2017老C的方块
网络流真的是一种神奇的算法.在一张图上面求感觉高度自动化的方案一般而言好像都是网络流的主阵地.讲真一开始看到这道题也有点懵,题面很长,感觉很难的样子.不过,仔细阅读了题意之后明白了:我们所要做的就是要 ...
- BZOJ 4823: [Cqoi2017]老C的方块
分析: 我觉得我的网络流白学了...QAQ... 其实数据范围本是无法用网络流跑过去的,然而出题者想让他跑过去,也就跑过去了... 看到题目其实感觉很麻烦,不知道从哪里入手,那么仔细观察所给出的有用信 ...
随机推荐
- UE4蓝图小记
http://www.element3ds.com/forum.php?mod=viewthread&tid=76930&page=1&authorid=104414 http ...
- Vue 编程之路(二)——跳转页面传值
最近公司的一个项目中使用 Vue 2.0 + element UI 实现一个后台管理系统的前端部分,属于商城类型.其中我负责的部分有一项需要跳转页面,由于跳转前的页面是多个组件构成的,所以在跳转页面的 ...
- 搭建hexo博客并部署到github上
hexo是由Node.js驱动的一款快速.简单且功能强大的博客框架,支持多线程,数百篇文章只需几秒即可生成.支持markdown编写文章,可以方便的生成静态网页托管在github上. 感觉不错. 前端 ...
- (转)Shadow Mapping
原文:丢失,十分抱歉,这篇是在笔记上发现的.SmaEngine 阴影和级联部分是模仿UE的结构设计 This tutorial will cover how to implement shadow ...
- C Program进阶-二维数组动态内存开辟
对于二维数组,我们知道可以用Type ArrayName[Row][Colume]的方式来定义,这是一种静态内存开辟的方式,程序在编译的时候就为该数组分配了空间,而且行和列大小也是指定的.这篇文章里我 ...
- 20172330 2017-2018-1 《Java程序设计》第九周学习总结
20172330 2017-2018-1 <程序设计与数据结构>第九周学习总结 教材学习内容总结 本周的学习包括两章内容,分别为异常和递归. 异常 错误和异常都是对象,代表非正常情况或者无 ...
- UML建模语言入门 -- 静态图详解 类图 对象图 包图 静态图建模实战
发现个好东西思维导图, 最近开始用MindManager整理博客 . 作者 :万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/deta ...
- C#语言使用redis
文章:Redis总结(二)C#中如何使用redis 文章:Redis总结(三)Redis 的主从复制 文章:Redis总结(四)Redis 的持久化
- 项目uml
[团队信息] 团队项目: 小葵日记--主打记录与分享模式的日记app 队名:日不落战队 队员信息及贡献分比例: 短学号 名 本次作业博客链接 此次作业任务 贡献分配 备注 501 安琪 http:// ...
- <Effective C++>读书摘要--Inheritance and Object-Oriented Design<二>
<Item 36> Never redefine an inherited non-virtual function 1.如下代码通过不同指针调用同一个对象的同一个函数会产生不同的行为Th ...