[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... 其实数据范围本是无法用网络流跑过去的,然而出题者想让他跑过去,也就跑过去了... 看到题目其实感觉很麻烦,不知道从哪里入手,那么仔细观察所给出的有用信 ...
随机推荐
- VINS(七)estimator_node 数据对齐 imu预积分 vision
首先通过vins_estimator mode监听几个Topic(频率2000Hz),将imu数据,feature数据,raw_image数据(用于回环检测)通过各自的回调函数封装起来 ros::Su ...
- 用wireshark查看 tcpdump 抓取的mysql交互数据
用tcpdump 抓取 mysql客户端与服务器端的交互 1开启tcpdump tcpdump -i eth0 -s 3000 port 3306 -w ~/sql.pcap 先故意输入一个错误的密 ...
- Matlab2018年最新视频教程视频讲义(包含代码)
2018年Matlab最新视频教程视频讲义(包含代码),适合初学者入门进阶学习,下载地址:百度网盘, https://pan.baidu.com/s/1w4h297ua6ctzfturQ1791g 内 ...
- iWebShop安装教程
要进行iWebShop测试,要先在本地电脑上安装iWebShop运行环境,之后再安装iWebShop程序,接下来我就一步步讲解,如何安装iWebShop程序. ##一.运行环境搭建 这里我推荐新手使用 ...
- java基础-Comparator接口与Collections实现排序算法
java 排序Comparable和Comparator使用 java提供了两个排序用的接口Comparable和Comparator,一般情况下使用区别如下: Comparable 接口用于类的固定 ...
- HPUX 11.31 MC/SG恢复丢失的锁盘
有时候由于一些特殊的原因,用户的cluster中的锁盘信息丢失,或者需要更换锁盘,只要执行一个命令就可以了. #cmdisklock reset /dev/vglock:/dev/disk/diskX ...
- IntelliJ IDEA 2017.3/2018.1/.2 激活
传统的License Server方式已经无法注册IntelliJ IDEA2017.3的版本了. http://idea.lanyus.com,这个网站有破解补丁和注册码两种方式,另外http:// ...
- PHP 签到,与时间获取,数组长度获取
本文实例讲述了php实现签到功能的方法.分享给大家供大家参考,具体如下:首先我在数据库里建了两张表,一个是用户的积分表,一个是签到状态表,分来用来记录用户的积分数和先到状态 在用户签到状态表中我们有一 ...
- TCP系列34—窗口管理&流控—8、缓存自动调整
一.概述 我们之前介绍过一种具有大的带宽时延乘积(band-delay product.BDP)的网络,这种网络称为长肥网络(LongFatNetwork,即LFN).我们想象一种简单的场景,假设发送 ...
- 记一次dll强命名冲突事件
一 问题的出现 现在要做一个net分布式平台,平台涉及多个服务之间调用问题,最基础的莫过于sso.由于我们的sso采用了wcf一套私有框架实现,另外一个webapi服务通过接口调用sso服务.由于s ...