BZOJ 3774 最优选择 (最小割+二分图)
题目大意:给你一个网格图,每个格子都有$a_{ij}$的代价和$b_{ij}$的回报,对于格子$ij$,想获得$b_{ij}$的回报,要么付出$a_{ij}$的代价,要么$ij$周围四联通的格子都付出代价,求最大的回报-代价
好神的一道题,%%%jr
想获得$b_{ij}$的回报,要么付出$a_{ij}$的代价,要么$ij$周围四联通的格子都付出代价
所以把棋盘像国际象棋一样黑白交叉染色,原图就变成了一个类似于二分图的东西
每个格子都拆成$2$个点
对于白格子,源点$S$向$W1$连流量为$a_{ij}$的边,$W1$向$W2$连流量为$b_{ij}$的边,$W2$向白格子周围四个黑格子的$B2$连流量为$inf$的边
对于黑格子,$B2$向汇点$T$连流量为$a_{ij}$的边,$B1$向$B2$连流量为$b_{ij}$的边,周围四个白格子的$W1$向$B1$连流量为$inf$的边
然后跑最大流,答案就是总回报-最大流
为什么要这么建边?我们可以对割进行分析
如果一个白格子的代价边$a_{ij}$被割掉了,说明这个格子带来的回报$\geq$代价,被归到了$T$集合里,此时流量$=$代价,统计答案时会加上回报$-$代价
如果一个白格子的代价边$a_{ij}$没被割掉,说明这个格子带来的回报$<$代价,被归到了$S$集合里,此时流量$=$回报,统计答案时会把这部分回报去掉
黑格子也是同理
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 5010
#define M1 30010
#define L1 55
using namespace std;
const int inf=0x3f3f3f3f; int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
}
struct Edge{
int to[M1<<],nxt[M1<<],flow[M1<<],head[N1],cte;
void ae(int u,int v,int f)
{
cte++; to[cte]=v; nxt[cte]=head[u];
head[u]=cte; flow[cte]=f;
}
}e; int dep[N1],que[M1],cur[N1],n,m,hd,tl,S,T;
int bfs()
{
int x,j,v;
memset(dep,-,sizeof(dep)); memcpy(cur,e.head,sizeof(cur));
hd=,tl=; que[++tl]=S; dep[S]=;
while(hd<=tl)
{
x=que[hd++];
for(j=e.head[x];j;j=e.nxt[j])
{
v=e.to[j];
if( dep[v]==- && e.flow[j]> )
{
dep[v]=dep[x]+;
que[++tl]=v;
}
}
}
return dep[T]!=-;
}
int dfs(int x,int limit)
{
int j,v,flow,ans=;
if(!limit||x==T) return limit;
for(j=cur[x];j;j=e.nxt[j])
{
v=e.to[j]; cur[x]=j;
if( dep[v]==dep[x]+ && (flow=dfs(v,min(limit,e.flow[j]))) )
{
e.flow[j]-=flow; limit-=flow;
e.flow[j^]+=flow; ans+=flow;
if(!limit) break;
}
}
return ans;
}
int Dinic()
{
int mxflow=,j,v,ans=;
while(bfs())
mxflow+=dfs(S,inf);
return mxflow;
} int xx[]={-,,,},yy[]={,,,-};
int a[L1][L1],b[L1][L1],id[L1][L1];
inline int check(int x,int y){return (x<||y<||x>n||y>m)?:;} int main()
{
scanf("%d%d",&n,&m);
int i,j,x,y,k,tot=n*m,sum=; e.cte=; S=; T=tot+tot+;
for(i=;i<=n;i++) for(j=;j<=m;j++) a[i][j]=gint();// sum+=v[i][j];
for(i=;i<=n;i++) for(j=;j<=m;j++) b[i][j]=gint(), id[i][j]=(i-)*m+j, sum+=b[i][j];
for(i=;i<=n;i++) for(j=;j<=m;j++)
{
x=id[i][j];
if((i+j)&){
e.ae(S,x,a[i][j]); e.ae(x,S,);
e.ae(x,x+tot,b[i][j]); e.ae(x+tot,x,);
for(k=;k<;k++)
{
if(!check(i+xx[k],j+yy[k])) continue;
y=id[i+xx[k]][j+yy[k]];
e.ae(x+tot,y+tot,inf); e.ae(y+tot,x+tot,);
}
}else{
e.ae(x+tot,T,a[i][j]); e.ae(T,x+tot,);
e.ae(x,x+tot,b[i][j]); e.ae(x+tot,x,);
for(k=;k<;k++)
{
if(!check(i+xx[k],j+yy[k])) continue;
y=id[i+xx[k]][j+yy[k]];
e.ae(y,x,inf); e.ae(x,y,);
}
}
}
printf("%d\n",sum-Dinic());
return ;
}
BZOJ 3774 最优选择 (最小割+二分图)的更多相关文章
- BZOJ 3774: 最优选择( 最小割 )
最小割...二分染色然后把颜色不同的点的源汇反过来..然后就可以做了. 某个点(x,y): S->Id(x,y)(回报), Id(x,y)->T(代价), Id(i,j)&& ...
- [BZOJ 3774] 最优选择 【最小割】
题目链接:BZOJ - 3774 题目分析 此题与“文理分科”那道题目有些类似.都是使用最小割来求解,先加上可能获得的权值,在减掉必须舍弃的权值(最小割). 文理分科是规定每个人和 S 连就是选文,和 ...
- 【BZOJ3774】最优选择 最小割
[BZOJ3774]最优选择 Description 小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择 ...
- 【最小割/二分图最大独立集】【网络流24题】【P2774】 方格取数问题
Description 给定一个 \(n~\times~m\) 的矩阵,每个位置有一个正整数,选择一些互不相邻的数,最大化权值和 Limitation \(1~\leq~n,~m~\leq~100\) ...
- BZOJ 1934 Vote 善意的投票(最小割+二分图)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1934 题目大意: 幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题 ...
- BZOJ 2039 人员雇佣 二元关系 最小割
题面太长了,请各位自行品尝—>人员雇佣 分析: 借用题解的描述: a.选择每个人有一个代价Ai b.如果有两个人同时选择就可以获得收益Ei,j c.如果一个人选择另一个不选会产生代价Ei,j 这 ...
- POJ3308 Paratroopers(最小割/二分图最小点权覆盖)
把入侵者看作边,每一行每一列都是点,选取某一行某一列都有费用,这样问题就是选总权最小的点集覆盖所有边,就是最小点权覆盖. 此外,题目的总花费是所有费用的乘积,这时有个技巧,就是取对数,把乘法变为加法运 ...
- BZOJ 1497: [NOI2006]最大获利 最小割
1497: [NOI2006]最大获利 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1497 Description 新的技术正冲击着手 ...
- bzoj 1391 [Ceoi2008]order(最小割)
[题意] 有n个有偿工作选做,m个机器,完成一个工作需要若干个工序,完成每个工序需要一个机器,对于一个机器,在不同的工序有不同的租费,但买下来的费用只有一个.问最大获益. [思路] 对于工作和机器建点 ...
随机推荐
- 草草搞了个SERVLET的注册登陆功能
按书来的,学习阶段,一切都好新奇..至少对比于DJANGO,好像复杂点点,但HTTP的东东,是相通的哈. package cc.openhome.controller; import java.io. ...
- Maven错误:XXX时出错; invalid LOC header (bad signature)的解决方法
错误原因是该包没下载成功,比如网络问题等因素. 解决方法:进入本地仓库删除该包,然后再执行打包或部署等操作即可.
- Mysql查询缓存研究
转载声明:本文为DBA+社群原创文章,转载必须连同本订阅号二维码全文转载,并注明作者名字及来源:DBA+社群(dbaplus). http://mp.weixin.qq.com/s?__biz=MzI ...
- [React] Capture values using the lifecycle hook getSnapshotBeforeUpdate in React 16.3
getSnapshotBeforeUpdate is a lifecycle hook that was introduced with React 16.3. It is invoked right ...
- redhat gitlab的搭建
http://www.cnblogs.com/derekchen/p/5870723.html 1.新建 /etc/yum.repos.d/gitlab-ce.repo,添加以下内容 [gitlab- ...
- The Triangle--nyoj 18
The Triangle 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 (Figure 1) Figure ...
- [javaEE] Eclipse 默认设置的换行长度
eclipse 默认设置的换行长度, 格式化代码后,经常换行,非常难看. 1.Java代码 打开Eclipse的Window菜单,然后 Preferences->Java->Code St ...
- Object源码分析(一)
刚注册博客,准备学习一下java源码,当然首先从Object看起. 介绍一下Object: Object是所有类层次结构的根,所有的类都将Object作为超类.所有的对象,包括数组,都实现了Objec ...
- spy++ 句柄消息详解
使用spy++捕获到的消息详解 主要是今天正好自己用到. 原来也有用过SPY++查看消息,然后自己SendMessage或者PostMessage 直接发送消息给目标程序.但是原来一用就有效果,今天要 ...
- shp系列(六)——利用C++进行Dbf文件的写(创建)
上一篇介绍了shp文件的创建,接下来介绍dbf的创建. 推荐结合读取dbf的博客一起看! 推荐结合读取dbf的博客一起看! 推荐结合读取dbf的博客一起看! 1.Dbf头文件的创建 Dbf头文件的结构 ...