[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... 其实数据范围本是无法用网络流跑过去的,然而出题者想让他跑过去,也就跑过去了... 看到题目其实感觉很麻烦,不知道从哪里入手,那么仔细观察所给出的有用信 ...
随机推荐
- OpenCV 3.2 Tracking 物体跟踪
跟踪就是在连续视频帧中定位物体,通常的跟踪算法包括以下几类: 1. Dense Optical Flow 稠密光流 2. Sparse Optical Flow 稀疏光流 最典型的如KLT算法(Kan ...
- ORB-SLAM(六)MapPoint与Map
地图点可以通过关键帧来构造,也可以通过普通帧构造,但是最终,必须是和关键帧对应的,通过普通帧构造的地图点只是临时被Tracking用来追踪用的. 构造函数(地图点3D坐标及其参考帧): // 参考帧是 ...
- dubbo之注册管理中心
一.在dubbo的框架中注册中心是必要的一个环节,这个也是分布式部署的一个必要环节.在dubbo的架构基本图中可以看出,基本上所有的服务都是通过注册中心进行注册,然后在通过注册中心,暴露出接口来. 二 ...
- hdu5305 Friends(dfs,多校题)
Friends Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- Linux命令应用大词典-第32章 性能监控
32.1 sar:收集.报告或保存系统活动信息 32.2 iostat:报告CPU统计数据和设备.分区输入.输出消息 32.3 iotop:进行I/O监控 32.4 mpstat:报告CPU相关的统计 ...
- TPO-13 C1 Understand the assignment in psychology course
TPO-13 C1 Understand the assignment in psychology course 第 1 段 1.listen to a conversation between a ...
- CSP201403-2:窗口
引言:CSP(http://www.cspro.org/lead/application/ccf/login.jsp)是由中国计算机学会(CCF)发起的"计算机职业资格认证"考试, ...
- 《Effective C++》读书笔记 被你忽略的关于构造析构赋值
如果程序员没有定义,那么编译器会默认隐式为你创建一个copy构造函数,一个copy赋值操作符,一个析构函数.另外如果你没有声明任何构造函数,编译器会为你声明一个default构造函数. 但是只有当这些 ...
- Apache POI:Excel读写库
1)Apache POI 简介 Apache POI是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office格式档案读和写 ...
- UVa 1586 - Molar Mass - ACM/ICPC Seoul 2007 - C语言
关键在于判断数字是两位数还是单位数,其他部分没有难度. #include"stdio.h" #include"string.h" #include"c ...