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

  实际上之前做过一道非常毒瘤的网络流题目【无限之环】。当时就思考了一下:为什么出题人规定不能旋转直线管子?原因就是因为这样的图建不出来,它与不具有其他的管子的特点。那么可以断定:给出的这四个图案必然也是非常特殊的图形,否则不会只有这四个/不会是这四个。于是观察这四个图案,不难发现它们的特征:以一对中间夹了特殊边的方块为中心,分别有另一方块随意连接在上方。

  我们从这个中心开始入手:由于要求最小值,所以-->最小割 / 费用流。但一个直观的感觉,它是在很多的方案当中做出选择,与最小割是比较贴合的。(每一种图案牵扯到四个方块,拿掉任何一个就可以破坏这个图形)如果每一种方案彼此平行,只需建出图暴力跑即可。可是会有交叉:当我们删去一个方块时,可能同时破坏了两个方案。

  观察图案,由于上下,左右交错,一个中心只可能出现在一个方案中,但其两侧的方块却可能出现在不同的方案当中。于是我们对于这样两侧的方块进行黑白染色,保证每一种方案当中所牵涉到的另两个方块分别属于不同的颜色(由于题目的特殊性质是可以做到的)。

  那么建边的方式也十分的自然了:

  源点-->所有白色的点,边权为代价;所有白色的点-->中心连边,边权为INF;所有的中心 = 两条边 = 边权为各个方块的代价。所有的中心 --> 黑点,黑点 --> 汇点,边权为代价。此时的最小割所代表的意义即为我们做出的最小代价方案选择。

  做出这题还是比较开心的,代码跑得也很快。不过细节比较多,要注意一下……

// luogu-judger-enable-o2
#include <bits/stdc++.h>
using namespace std;
#define maxn 300000
#define maxm 800000
#define ll long long
#define INF 9999999
int C, R, n, S, T, tot;
int Color[maxn], cnt;
int cnp = , head[maxn], cur[maxn];
int lev[maxn];
map <int, int> Map;
int dx[] = {, , , , , , -, -, -, -};
int dy[] = {-, , , , -, , -, , , }; struct edge
{
int to, last, f;
}E[maxm]; struct node
{
int x, y, w;
}P[maxn]; bool cmp(node a, node b)
{
if(a.x != b.x) return a.x < b.x;
return a.y < b.y;
} int read()
{
int x = , k = ;
char c;
c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} void add(int u, int v, int f)
{
E[cnp].to = v, E[cnp].f = f, E[cnp].last = head[u], head[u] = cnp ++;
E[cnp].to = u, E[cnp].f = , E[cnp].last = head[v], head[v] = cnp ++;
} bool Bfs()
{
queue <int> q;
memset(lev, , sizeof(lev));
q.push(S); lev[S] = ;
while(!q.empty())
{
int u = q.front(); q.pop();
for(int i = head[u]; i; i = E[i].last)
{
int v = E[i].to;
if(!lev[v] && E[i].f)
{
lev[v] = lev[u] + ;
q.push(v);
}
}
if(lev[T]) return ;
}
return ;
} int Dfs(int u, int nf)
{
if(u == T) return nf;
int lf = ;
for(int i = cur[u]; i; i = E[i].last)
{
int v = E[i].to;
if(lev[v] == lev[u] + && E[i].f)
{
int af = Dfs(v, min(E[i].f, nf));
nf -= af, lf += af;
E[i].f -= af, E[i ^ ].f += af;
if(!nf) return lf;
cur[u] = i;
}
}
if(!lf) lev[u] = -;
return lf;
} int Dinic()
{
int ans = ;
while(Bfs())
{
memcpy(cur, head, sizeof(head));
ans += Dfs(S, INF);
}
return ans;
} int id(int x, int y)
{
ll k = 1ll * R * (x - ) + 1ll * y;
if(Map[k]) return Map[k];
else return Map[k] = ++ tot;
} int Check(int x, int y)
{
ll k = 1ll * R * (x - ) + 1ll * y;
if(Map[k]) return Map[k];
else return ;
} void Get_Graph(int p)
{
int a = ++ tot, b = ++ tot, c = ++ tot;
add(a, b, P[p].w); add(b, c, P[p + ].w);
for(int i = ; i < ; i ++)
{
int xx = P[p].x + dx[i], yy = P[p].y + dy[i], tem;
if(xx < || xx > C || yy < || yy > R) continue;
if(tem = Check(xx, yy))
{
if(Color[tem] == ) add(tem, a, INF);
else add(c, tem, INF);
}
}
} int main()
{
C = read(), R = read();
swap(C, R); n = read();
S = , T = * n + ;
for(int i = ; i <= n; i ++)
{
int x = read(), y = read(), w = read();
swap(x, y);
if((x & ) && ((!((y - ) % )) || (!((y - ) % ))))
{
P[++ cnt].x = x, P[cnt].y = y;
P[cnt].w = w; continue;
}
if((!(x & )) && ((!((y - ) % )) || (!((y - ) % ))))
{
P[++ cnt].x = x, P[cnt].y = y;
P[cnt].w = w; continue;
}
if(x & )
{
if(((y - ) % )) add(S, id(x, y), w), Color[id(x, y)] = ;
else add(id(x, y), T, w), Color[id(x, y)] = ;
}
else
{
if(!((y - ) % )) add(id(x, y), T, w), Color[id(x, y)] = ;
else add(S, id(x, y), w), Color[id(x, y)] = ;
}
}
sort(P + , P + + cnt, cmp);
for(int i = ; i <= cnt; i += )
{
if(P[i + ].x != P[i].x) continue;
if(P[i + ].y != P[i].y + ) continue;
Get_Graph(i);
}
printf("%d\n", Dinic());
return ;
}

【题解】CQOI2017老C的方块的更多相关文章

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

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

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

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

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

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

  4. BZOJ4823 [Cqoi2017]老C的方块 【最小割】

    题目 老C是个程序员. 作为一个懒惰的程序员,老C经常在电脑上玩方块游戏消磨时间.游戏被限定在一个由小方格排成的R行C列网格上,如果两个小方格有公共的边,就称它们是相邻的,而且有些相邻的小方格之间的公 ...

  5. [bzoj4823][洛谷P3756][Cqoi2017]老C的方块

    Description 老 C 是个程序员. 作为一个懒惰的程序员,老 C 经常在电脑上玩方块游戏消磨时间.游戏被限定在一个由小方格排成的R行C列网格上 ,如果两个小方格有公共的边,就称它们是相邻的, ...

  6. [CQOI2017]老C的方块 网络流

    ---题面--- 题解: 做这题做了好久,,,换了4种建图QAQ 首先我们观察弃疗的形状,可以发现有一个特点,那就是都以一个固定不变的特殊边为中心的,如果我们将特殊边两边的方块分别称为s块和t块, 那 ...

  7. [bzoj4823][Cqoi2017]老C的方块

    来自FallDream的博客,未经允许,请勿转载,谢谢. 挺有意思的一道题.... 看完题面比较明确是最小割,考虑怎么建图 想了比较久 突破口应该是题目中那张奇怪的图 观察这个奇怪的图和方块,很容易发 ...

  8. [CQOI2017]老C的方块

    题目描述 https://www.lydsy.com/JudgeOnline/problem.php?id=4823 题解 观察那四种条件 有没有什么特点? 我们可以把蓝线两边的部分看做两个区域,这样 ...

  9. bzoj千题计划300:bzoj4823: [Cqoi2017]老C的方块

    http://www.lydsy.com/JudgeOnline/problem.php?id=4823 讨厌的形状就是四联通图 且左右各连一个方块 那么破坏所有满足条件的四联通就好了 按上图方式染色 ...

随机推荐

  1. 三角形div原理(小知识点)

    三角形div其实就是从边框的演变过程 #sider2{ width: 100px; height: 100px; border-top: 30px solid #000; border-right:  ...

  2. Delphi 过程类型

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  3. Volatile的详解

    volatile关键字修饰的共享变量主要有两个特点:1.保证了不同线程访问的内存可见性    2.禁止重排序 在说内存可见性和有序性之前,我们有必要看一下Java的内存模型(注意和JVM内存模型的区分 ...

  4. 国内maven库链接地址,链接阿里的库,下载很快!!!

    <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http:/ ...

  5. keil5 mdk使用ST-Link II下载出现cannot halt the core解决办法

    在正常的程序里面,我添加了MB85RS16(spi flash)这个外设驱动代码后,使用ST-Link II下载就出现cannot halt the core. 这个现象之前出现过1次,但是解决办法忘 ...

  6. Python基础教程学记(1)

    引言 Python是什么?——Python是一种面向对象的解释性高级编程语言,具有动态语义.这句话的要点在于,Python是一种知道如何不妨碍你编写程序的编程语言.它让你能够毫无困难地实现所需的功能, ...

  7. windows环境下,用python绘图库matplotlib绘图时中文乱码问题

    1.下载中文字体(看自己爱好就行)下面这个举例: SimHei - Free Font Download​www.fontpalace.co 2.下载之后,打开即可安装,将字体安装进windows系统 ...

  8. Python学习:2.Python集成学习环境(IDE)Pycharm的安装配置以及激活方

    一.下载Pycharm Pycharm作为Python现在最流行的集成开发环境,我们今后的Python的学习也就使用Pycharm进行,那今天我们就讲一下Pycharm的安装配置以及激活 1.我们首先 ...

  9. 局域网访问不到linux下的tomcat

    问题描述: CentOS安装完成Tomcat后,访问本地:http://localhost:8080/正确.但局域网内无法访问,而且服务器可ping通 经查原因为防火墙开启: [root@localh ...

  10. 利用JS调取电脑摄像头,实现拍照功能

    1.调取电脑摄像头非常简单,看代码一幕了然 window.addEventListener("DOMContentLoaded", function() { var canvas ...