方案合法相当于要求接口之间配对,黑白染色一波,考虑网络流。有一个很奇怪的限制是不能旋转直线型水管,考虑非直线型水管有什么特殊性,可以发现其接口都是连续的。那么对于旋转水管,可以看做是把顺/逆时针方向上最后的接口提到最前。于是用四个点表示某格子的四个方向,以上述方式只移动一次就能相互转换的方向之间连费用1的边。然后在相邻格子可以相互匹配的方向之间连边,跑费用流即可。注意费用流的无向边必须按有向边的方式建反向边。不明白讨论一大串的是在干啥。

  

  然后就非常悲惨了。多路增广的费用流会跑的很快,然而并不会。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 10010
#define K 2010
#define S 10001
#define T 10002
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,id[K][],p[N],d[N],q[N],pre[N],t=-,cnt,tot,ans,val;
bool flag[N];
struct data{int to,nxt,cap,flow,cost;
}edge[N<<];
void addedge(int x,int y,int z,int cost)
{
t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].cap=z,edge[t].flow=,edge[t].cost=cost,p[x]=t;
t++;edge[t].to=x,edge[t].nxt=p[y],edge[t].cap=,edge[t].flow=,edge[t].cost=-cost,p[y]=t;
}
inline int trans(int x,int y){return (x-)*m+y;}
inline bool isblack(int x,int y){return (x&)^(y&);}
inline int inc(int &x){x++;if (x>cnt+) x-=cnt+;return x;}
bool spfa()
{
memset(d,,sizeof(d));d[S]=;
memset(flag,,sizeof(flag));
int head=,tail=;q[]=S;
do
{
int x=q[inc(head)];flag[x]=;
for (int i=p[x];~i;i=edge[i].nxt)
if (d[x]+edge[i].cost<d[edge[i].to]&&edge[i].flow<edge[i].cap)
{
d[edge[i].to]=d[x]+edge[i].cost;
pre[edge[i].to]=i;
if (!flag[edge[i].to]) q[inc(tail)]=edge[i].to,flag[edge[i].to]=;
}
}while (head!=tail);
return d[T]<N;
}
void ekspfa()
{
while (spfa())
{
int v=;
for (int i=T;i!=S;i=edge[pre[i]^].to)
if (edge[pre[i]].cap==edge[pre[i]].flow) {v=;break;}
if (v)
{
ans++;
for (int i=T;i!=S;i=edge[pre[i]^].to)
val+=edge[pre[i]].cost,edge[pre[i]].flow++,edge[pre[i]^].flow--;
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj5120.in","r",stdin);
freopen("bzoj5120.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read();
memset(p,,sizeof(p));
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
{
int x=read(),u=,v=trans(i,j);
for (int k=;k<;k++)
{
id[v][k]=++cnt;
if (x&(<<k)) u++,isblack(i,j)?addedge(S,cnt,,):addedge(cnt,T,,);
}
tot+=u;
if (x==||x==) continue;
if (u==||u==) for (int k=;k<;k++) addedge(id[v][k],id[v][k+&],,),addedge(id[v][k+&],id[v][k],,);
if (u==)
{
addedge(id[v][],id[v][],,),addedge(id[v][],id[v][],,);
addedge(id[v][],id[v][],,),addedge(id[v][],id[v][],,);
}
}
if (tot&) {cout<<-;return ;}tot>>=;
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
if (isblack(i,j))
{
int v=trans(i,j);
if (i>) addedge(id[v][],id[trans(i-,j)][],,);
if (j<m) addedge(id[v][],id[trans(i,j+)][],,);
if (i<n) addedge(id[v][],id[trans(i+,j)][],,);
if (j>) addedge(id[v][],id[trans(i,j-)][],,);
}
ekspfa();
if (ans<tot) cout<<-;
else cout<<val;
return ;
}

BZOJ5120 无限之环(费用流)的更多相关文章

  1. BZOJ5120 [2017国家集训队测试]无限之环 费用流

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ5120 题意概括 原题挺简略的. 题解 本题好难. 听了任轩笛大佬<国家队神犇>的讲课才 ...

  2. BZOJ.5120.[清华集训2017]无限之环(费用流zkw 黑白染色)

    题目链接 LOJ 洛谷 容易想到最小费用最大流分配度数. 因为水管形态固定,每个点还是要拆成4个点,分别当前格子表示向上右下左方向. 然后能比较容易地得到每种状态向其它状态转移的费用(比如原向上的可以 ...

  3. BZOJ 5120: [2017国家集训队测试]无限之环(费用流)

    传送门 解题思路 神仙题.调了一个晚上+半个上午..这道咋看咋都不像图论的题竟然用费用流做,将行+列为奇数的点和偶数的点分开,也就是匹配问题,然后把一个点复制四份,分别代表这个点的上下左右接头,如果有 ...

  4. [BZOJ5120]无限之环

    Description 曾经有一款流行的游戏,叫做InfinityLoop,先来简单的介绍一下这个游戏: 游戏在一个n×m的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在方格某些方向的边界的中 ...

  5. 洛谷P4003 无限之环(infinityloop)(网络流,费用流)

    洛谷题目传送门 题目 题目描述 曾经有一款流行的游戏,叫做 Infinity Loop,先来简单的介绍一下这个游戏: 游戏在一个 n ∗ m 的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在格 ...

  6. LOJ2321. 「清华集训 2017」无限之环【费用流】

    LINK 很好的一道网络里题 首先想插头DP的还是出门左转10分代码吧 然后考虑怎么网络流 首先要保证没有漏水 也就是说每个接口一定要有对应的接口 那么发现每个点只有可能和上下左右四个点产生联通关系 ...

  7. bzoj 5120 无限之环 & 洛谷 P4003 —— 费用流(多路增广SPFA)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5120 https://www.luogu.org/problemnew/show/P4003 ...

  8. 洛谷P4003 无限之环(费用流)

    传送门 神仙题啊……不看题解我可能一年都不一定做得出来……FlashHu大佬太强啦 到底是得有怎样的脑回路才能一眼看去就是费用流啊…… 建好图之后套个板子就好了,那么我们着重来讨论一下怎么建图 首先, ...

  9. LOJ 2321 清华集训2017 无限之环 拆点+最小费用最大流

    题面:中文题面,这里不占用篇幅 分析: 看到题面,我就想弃疗…… 但是作为任务题单,还是抄了题解…… 大概就是将每个格子拆点,拆成五个点,上下左右的触点和一个负责连源汇点的点(以下简称本点). 这个这 ...

随机推荐

  1. netty+proto使用简要记录

    1. maven环境配置protobuf 2.生成.proto文件 3.将.proto转为java文件 打开电脑的cmd,进入.proto所在文件位置,输入命令:protoc.exe --java_o ...

  2. C++构造函数和析构函数什么情况下会用

    析构函数: 1. 对象生命周期结束,被销毁时: 2. delete 指向对象的指针时: 3. delete 指向基类对象的指针时,其析构函数是虚函数: 4. 在嵌套关系中,对象A是对象B的成员,当对象 ...

  3. Elasticsearch Java client(ES Client 简介、Java REST Client、Java Client、Spring Data Elasticsearch)

    elasticsearch系列七:ES Java客户端-Elasticsearch Java client(ES Client 简介.Java REST Client.Java Client.Spri ...

  4. centos7 上安装mysql5.7后登录报错ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: Yes 或者No)

    原文转载自以下链接:https://blog.csdn.net/keepd/article/details/77151006 安装完mysql后会有个临时密码去日志查看,但是查看登录修改密后还是不行 ...

  5. Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第7节: 获取异线程释放的对象

    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第七节: 获取异线程释放的对象 上一小节分析了异线程回收对象, 原理是通过与stack关联的WeakOrder ...

  6. 使用Zabbix的SNMP trap监控类型监控设备的一个例子

    本文以监控绿盟设备为例. 1.登录被监控的设备的管理系统,配置snmptrap地址指向zabbix服务器或代理服务器. snmptrap地址也叫陷阱. 2.验证是否能在zabbix服务器或代理服务器上 ...

  7. 从零开始的Python学习Episode 20——面向对象(3)

    面向对象之封装 封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别:将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体. 隐藏 在python中用双下划线开 ...

  8. Python交互数据库(Mysql | Mongodb | Redis)

    数据库 Mysql Mysql MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,后来被Sun公司收购,Sun公司后来又被Oracle公司收购,目前属于Oracle旗下产品 MyS ...

  9. rest_framework_api规范

    目录 一.什么是RESTful 二.什么是API 三.RESTful API规范 四.基于Django实现API 五.基于Django Rest Framework框架实现 一. 什么是RESTful ...

  10. 元素transform: rotate()之后,元素宽高该怎么计算?

    通常,利用transform: rotate()元素之后,我们并不会去在意元素大小的变化,因为看上去并没有什么变化.虽然看上去没有变化,其实是有变化的.下面用一个例子来说明一下. html: < ...