洛谷P4003 无限之环(费用流)
神仙题啊……不看题解我可能一年都不一定做得出来……FlashHu大佬太强啦
到底是得有怎样的脑回路才能一眼看去就是费用流啊……
建好图之后套个板子就好了,那么我们着重来讨论一下怎么建图
首先,对于每一个水管的支管,有且仅有一个其他支管与他相连,那么就不会漏水了。用网络流的说法,就是要每个支管容量只能为1且必须满流
然而因为最优情况图可能会被分成好几个连通块,于是我们得强制所有相邻的格子都有流量才行(就是确保连通块不管怎么划分都能流)
那么黑白染色冷静一下……黑点连源,白点连汇
然后费用是因为旋转产生的……然后因为和四周都有连边所以要拆点
把每一个点拆成上下左右中,中间为原点,四周代表四个方向的水管。中间点连上源或汇,四周的点分别向能到达的接触点连边,容1费0
然后讨论旋转产生的费用……坐稳了……
先是直线型

比如射线指向上面,那么就让左下右的点连上面,左右点连边容1费1(转一次就行),下面的点连边容1费2(要转两次)
然后直角的

转一次会变成这样

那么就可以看做是上面的点跑到下面来了,那么上下建一条容1费1的边就好,左右同理。如果转了两次,刚好可以从上右一起流,费2,所以不用新加边了
最后第三种

如果顺时针转一次相当于左边到了下面,于是连边容1费1,同理下右连边容1费1,上下连边容1费2(因为上下转换要转两次)
然后其他都和以上一样分类讨论就行了
上代码吧,写的zkw费用流
//minamoto
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
#define UP(x) x+turn*sum
#define RI(x) x+((turn+1)&3)*sum
#define DO(x) x+((turn+2)&3)*sum
#define LE(x) x+((turn+3)&3)*sum
#define MD(x) x+(sum<<2)//上面几个用来计算对应点的数组下标,上下左右中。。。
const int N=,M=;
int sum,S=,T;
int head[N],Next[M],ver[M],edge[M],cost[M],tot=;
int dis[N],vis[N],cur[N],ans;
int n,m,k=,totf,turn;
inline void add(int u,int v,int e,int c,int tp){
//tp表示点的颜色,如果是白点所有边都要反向,为了让流流向汇点
if(tp) u^=v^=u^=v;
ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e,cost[tot]=c;
ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=,cost[tot]=-c;
}
queue<int> q;
bool spfa(){
memset(dis,-,sizeof(dis));
memset(vis,,sizeof(vis));
memcpy(cur,head,sizeof(int)*(T-S+));
q.push(T),dis[T]=,vis[T]=;
while(!q.empty()){
int u=q.front();q.pop(),vis[u]=;
for(int i=head[u];i;i=Next[i])
if(edge[i^]){
int v=ver[i],c=cost[i];
if(dis[v]<||dis[v]>dis[u]-c){
dis[v]=dis[u]-c;
if(!vis[v]) vis[v]=,q.push(v);
}
}
}
return ~dis[S];
}
int dfs(int u,int limit){
if(u==T||!limit) return limit;
int flow=,f;vis[u]=;
for(int &i=cur[u];i;i=Next[i]){
int v=ver[i];
if(dis[v]==dis[u]-cost[i]&&!vis[v]&&(f=dfs(v,min(limit,edge[i])))){
flow+=f,limit-=f;
edge[i]-=f,edge[i^]+=f;
ans+=f*cost[i];
if(!limit) break;
}
}
vis[u]=;
return flow;
}
int zkw(){
//zkw费用流板子
int flow=;
while(spfa()) flow+=dfs(S,inf);
return flow;
}
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read();
sum=n*m,T=sum*+;
for(int i=;i<n;++i)
for(int j=;j<m;++j,++k){
turn=;
int t=(i+j)&;
t?add(S,MD(k),inf,,):add(MD(k),T,inf,,);
if(i) add(DO(k-m),UP(k),,,t);
if(j) add(RI(k-),LE(k),,,t);
int op=read();
if(op&) add(UP(k),MD(k),,,t),++totf;
if(op&) add(RI(k),MD(k),,,t),++totf;
if(op&) add(DO(k),MD(k),,,t),++totf;
if(op&) add(LE(k),MD(k),,,t),++totf;
//统计一下总流量顺便和中间点连边
//因为每条边被记了两次,到时候要除以2
switch(op){
//直接把所有相同类型的一起处理掉
case :++turn;
case :++turn;
case :++turn;
case :
add(RI(k),UP(k),,,t);
add(DO(k),UP(k),,,t);
add(LE(k),UP(k),,,t);
break;
case :++turn;
case :++turn;
case :++turn;
case :
add(DO(k),UP(k),,,t);
add(LE(k),RI(k),,,t);
break;
case :++turn;
case :++turn;
case :++turn;
case :
add(DO(k),LE(k),,,t);
add(DO(k),UP(k),,,t);
add(DO(k),RI(k),,,t);
break;
}
}
printf("%d\n",(zkw()<<)==totf?ans:-);
return ;
}
洛谷P4003 无限之环(费用流)的更多相关文章
- 洛谷P4003 无限之环(infinityloop)(网络流,费用流)
洛谷题目传送门 题目 题目描述 曾经有一款流行的游戏,叫做 Infinity Loop,先来简单的介绍一下这个游戏: 游戏在一个 n ∗ m 的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在格 ...
- BZOJ.5120.[清华集训2017]无限之环(费用流zkw 黑白染色)
题目链接 LOJ 洛谷 容易想到最小费用最大流分配度数. 因为水管形态固定,每个点还是要拆成4个点,分别当前格子表示向上右下左方向. 然后能比较容易地得到每种状态向其它状态转移的费用(比如原向上的可以 ...
- BZOJ5120 [2017国家集训队测试]无限之环 费用流
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ5120 题意概括 原题挺简略的. 题解 本题好难. 听了任轩笛大佬<国家队神犇>的讲课才 ...
- 洛谷.4015.运输问题(SPFA费用流)
题目链接 嗯..水题 洛谷这网络流二十四题的难度评价真神奇.. #include <queue> #include <cstdio> #include <cctype&g ...
- 洛谷P4015 运输问题(费用流)
传送门 源点向仓库连费用$0$,流量为储量的边,商店向汇点连费用$0$,流量为需求的边,然后仓库向商店连流量$inf$,费用对应的边,跑个费用流即可 //minamoto #include<io ...
- 洛谷P4014 分配问题(费用流)
传送门 可以把原图看做一个二分图,人在左边,任务在右边,求一个带权的最大和最小完美匹配 然而我并不会二分图做法,所以只好直接用费用流套进去,求一个最小费用最大流和最大费用最大流即可 //minamot ...
- 洛谷 - P4452 - 航班安排 - 费用流
https://www.luogu.org/problemnew/show/P4452 又一道看题解的费用流. 注意时间也影响节点,像题解那样建边就少很多了. #include<bits/std ...
- BZOJ 5120: [2017国家集训队测试]无限之环(费用流)
传送门 解题思路 神仙题.调了一个晚上+半个上午..这道咋看咋都不像图论的题竟然用费用流做,将行+列为奇数的点和偶数的点分开,也就是匹配问题,然后把一个点复制四份,分别代表这个点的上下左右接头,如果有 ...
- bzoj 5120 无限之环 & 洛谷 P4003 —— 费用流(多路增广SPFA)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5120 https://www.luogu.org/problemnew/show/P4003 ...
随机推荐
- 《avascript 高级程序设计(第三版)》 ---第三章 基本概念
本章主要介绍Javasript语言的一些语法: 1.严格模式:开启:"use strict"; 2.变量:全部用var来定义,在函数中使用的称为局部变量,不能全局使用. 3.数据类 ...
- KafkaSpout 重复消费问题解决
使用https://github.com/nathanmarz/storm-contrib来对接Kafka0.7.2时, 发现kafkaSpout总会进行数据重读, 配置都无问题, 也没报错 进行de ...
- nodejs socket.io初探
1.安装socket.io npm install socket.io 2.创建服务端代码server.js var app = require('http').createServer(handle ...
- 「洛谷 P1801」黑匣子
好像很久没有更过博客了,因为博主这几周很忙.其实是在搞颓. 题意很难懂,所以就不重复了.其实是懒. 一眼看上去这是个 \(Splay\) 裸题,直接插入一个数,查询区间第 \(K\) 大,但是这样太不 ...
- IntelliJ IDEA 同时启动多个Tomcat实例端口是会冲突
- SpringBoot_Exception_02_Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:1.5.6.RELEASE:run
一.现象 上一个异常解决之后,出现了这个异常: [WARNING] The requested profile "pom.xml" could not be activated b ...
- codeforces 587B B. Duff in Beach(dp)
题目链接: B. Duff in Beach time limit per test 2 seconds memory limit per test 256 megabytes input stand ...
- linux 下errno各个值的意义(转) errno.h
strerror(errno):获取errno对应的错误 查看错误代码errno是调试程序的一个重要方法.当linux C api函数发生异常时,一般会将errno变量(需include errno. ...
- node.js Web应用框架Express入门指南
node.js Web应用框架Express入门指南 作者: 字体:[增加 减小] 类型:转载 时间:2014-05-28 我要评论 这篇文章主要介绍了node.js Web应用框架Express入门 ...
- uC/OS-II源码分析(三)
首先来了解下实时系统的基本概念: 1) 临界区,共享资源,任务(类似于进程),任务切换,任务调度,可剥夺型内核,可重入函数,动态优先级调度, 2) 如何处理优先级反转问题.这个问题描述如下:有三个任务 ...