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

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

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

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

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

  源点-->所有白色的点,边权为代价;所有白色的点-->中心连边,边权为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. hadoop生态搭建(3节点)-02.ssh配置

    # ssh免密码登录 # ==================================================================node1# 一路狂按回车,最终生成(id ...

  2. 爬虫之request模块高级

    一.cookie&session cookie:服务器端使用cookie来记录客户端的状态信息 实现流程: 执行登陆操作(获取cookie) 在发起个人主页请求时,需要将cookie携带到该请 ...

  3. python装饰器+递归+冒泡排序

    冒泡排序 li = [33, 2, 10, 1,23,23523,5123,4123,1,2,0] for k in range(1,len(li)): for i in range(len(li) ...

  4. 批量安装Python第三方库

    1.首先在python程序的文件夹内,新建一个文本文档,名字自定义,在文档中输入需要安装的第三方库,并用英文半角逗号隔开. import os def getTxt(): txt = open(&qu ...

  5. JavaSE基础复习---Class类与反射机制

    ---恢复内容开始--- 目录: 1.java.lang.class类 2.Java中的反射机制 3.运行时与编译时概念 1. java.lang.class类 Java程序在运行时,Java运行时系 ...

  6. 003---Python基本数据类型--列表

    列表 .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px ...

  7. Python3爬虫(二)网络爬虫的尺寸与约束

    Infi-chu: http://www.cnblogs.com/Infi-chu/ 一.网络爬虫的尺寸: 1.小规模,数据量小,爬取速度不敏感,Requests库,爬取网页 2.中规模,数据规模较大 ...

  8. go学习笔记-语言指针

    语言指针 定义及使用 变量是一种使用方便的占位符,用于引用计算机内存地址.取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址. 一个指针变量指向了一个值的内存地址.类似于变量和常量, ...

  9. python2.7入门---运算符 &案例

        已经分享过变量类型的基本概念了,接下来就研究了一下运算符的基础知识.接下来我们就来看一下内容.举个简单的例子 4 +5 = 9 .例子中,4 和 5 被称为操作数,"+" ...

  10. java 上溯造型与下塑造型

    父类: package com.neusoft.chapter07; public class Father { public int i = 1; public void say(){ System ...