【BZOJ3774】最优选择

Description

小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择了的。一个点如果被选择了,那么可以得到Bij的回报,现在请你帮小N选一个最优的方案,使得回报-代价尽可能大。

Input

第一行两个正整数N,M表示方格图的长与宽。

接下来N行每行M个整数Aij表示控制的代价。

接下来N行每行M个整数Bij表示选择的回报。

Output

一个整数,表示最大的回报-代价(如果一个都不控制那么就是0)。

Sample Input

3 3
1 100 100
100 1 100
1 100 100
2 0 0
5 2 0
2 0 0

Sample Output

8

HINT

对于100%的数据,N,M<=50,Aij,Bij都是小于等于100的正整数。

题解:忠告:不要看大爷的图!大爷说的挺明白,然后自己想了一个差不多的建图方法,一看大爷的图:这啥玩应?我和大爷建的不一样啊!一定是我错了!然后试图理解大爷的建图方法,得出结论:大爷太神了,这方法我理解不了。

还是来一个不那么神的,又好想又好理解的做法吧!

黑白染色是显然的啦,对于白点,我们钦定划分到T集代表选,然后讨论所有的情况:

1.四周选,当前点不选。划分到S集,代价0。

因为四周的点是黑点,划分到S集代表不选,而将当前点直接连向四周的点即可保证当前点与T集割开,所以连从当前点到四周的点,容量inf的边。

2.四周不选,当前点选。划分到T集,代价A。

我们需要让当前点花费A的代价即可以与S集割开,所以连从S到当前点,容量为A的边即可。

3.四周不选,当前点不选。划分到S集,代价B。

我们需要让当前点花费B的代价即可以与T割开,这个条件和情况1属于【或】关系,所以我们新建点b,设原来的是点a,将1中的边改为从b到四周的点,然后连从a到b,容量为B的边即可。

最终的图其实长这样:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
#define P(X,Y) ((X-1)*m+Y)
#define inf 1<<30
using namespace std;
int n,m,S,T,ans,cnt;
int A[60][60],B[60][60];
int to[100010],next[100010],head[100010],val[100010],d[10010];
int dx[]={0,1,0,-1},dy[]={1,0,-1,0};
queue<int> q;
inline void add(int a,int b,int c)
{
to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
to[cnt]=a,val[cnt]=0,next[cnt]=head[b],head[b]=cnt++;
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
inline int dfs(int x,int mf)
{
if(x==T) return mf;
int i,temp=mf,k;
for(i=head[x];i!=-1;i=next[i]) if(val[i]&&d[to[i]]==d[x]+1)
{
k=dfs(to[i],min(temp,val[i]));
if(!k) d[to[i]]=0;
temp-=k,val[i]-=k,val[i^1]+=k;
if(!temp) break;
}
return mf-temp;
}
inline int bfs()
{
memset(d,0,sizeof(d));
while(!q.empty()) q.pop();
d[S]=1,q.push(S);
int i,u;
while(!q.empty())
{
u=q.front(),q.pop();
for(i=head[u];i!=-1;i=next[i]) if(val[i]&&!d[to[i]])
{
d[to[i]]=d[u]+1;
if(to[i]==T) return 1;
q.push(to[i]);
}
}
return 0;
}
int main()
{
n=rd(),m=rd(),S=0,T=2*n*m+1;
int i,j,k,a,b,c;
memset(head,-1,sizeof(head));
for(i=1;i<=n;i++) for(j=1;j<=m;j++) A[i][j]=rd();
for(i=1;i<=n;i++) for(j=1;j<=m;j++) B[i][j]=rd(),ans+=B[i][j];
for(i=1;i<=n;i++) for(j=1;j<=m;j++)
{
if((i^j)&1)
{
a=P(i,j),b=P(i,j)+n*m;
add(S,a,A[i][j]),add(a,b,B[i][j]);
for(k=0;k<4;k++) if(i+dx[k]&&i+dx[k]<=n&&j+dy[k]&&j+dy[k]<=m)
{
c=P(i+dx[k],j+dy[k]),add(b,c,inf);
}
}
else
{
a=P(i,j),b=P(i,j)+n*m;
add(a,T,A[i][j]),add(b,a,B[i][j]);
for(k=0;k<4;k++) if(i+dx[k]&&i+dx[k]<=n&&j+dy[k]&&j+dy[k]<=m)
{
c=P(i+dx[k],j+dy[k]),add(c,b,inf);
}
}
}
while(bfs()) ans-=dfs(0,inf);
printf("%d",ans);
return 0;
}

【BZOJ3774】最优选择 最小割的更多相关文章

  1. BZOJ 3774: 最优选择( 最小割 )

    最小割...二分染色然后把颜色不同的点的源汇反过来..然后就可以做了. 某个点(x,y): S->Id(x,y)(回报), Id(x,y)->T(代价), Id(i,j)&& ...

  2. BZOJ 3774 最优选择 (最小割+二分图)

    题面传送门 题目大意:给你一个网格图,每个格子都有$a_{ij}$的代价和$b_{ij}$的回报,对于格子$ij$,想获得$b_{ij}$的回报,要么付出$a_{ij}$的代价,要么$ij$周围四联通 ...

  3. bzoj3774 最优选择

    题目描述: 小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择了的.一个点如果被选择了,那么可以得到Bi ...

  4. ZOJ 2676 Network Wars(最优比例最小割)

    Network Wars Time Limit: 5 Seconds      Memory Limit: 32768 KB      Special Judge Network of Bytelan ...

  5. 【bzoj3774】最优选择 网络流最小割

    题目描述 小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择了的.一个点如果被选择了,那么可以得到Bij ...

  6. [BZOJ 3774] 最优选择 【最小割】

    题目链接:BZOJ - 3774 题目分析 此题与“文理分科”那道题目有些类似.都是使用最小割来求解,先加上可能获得的权值,在减掉必须舍弃的权值(最小割). 文理分科是规定每个人和 S 连就是选文,和 ...

  7. 最大流&最小割 - 专题练习

    [例1][hdu5889] - 算法结合(BFS+Dinic) 题意 \(N\)个点\(M\)条路径,每条路径长度为\(1\),敌人从\(M\)节点点要进攻\(1\)节点,敌人总是选择最优路径即最短路 ...

  8. LOJ_6045_「雅礼集训 2017 Day8」价 _最小割

    LOJ_6045_「雅礼集训 2017 Day8」价 _最小割 描述: 有$n$种减肥药,$n$种药材,每种减肥药有一些对应的药材和一个收益. 假设选择吃下$K$种减肥药,那么需要这$K$种减肥药包含 ...

  9. cf786E ALT (最小割+倍增优化建图)

    如果把“我全都要”看作是我全不要的话,就可以用最小割解决啦 源点S,汇点T 我们试图让每个市民作为一个等待被割断的路径 把狗狗给市民:建边(S,i,1),其中i是市民 把狗狗给守卫:建边(j,T,1) ...

随机推荐

  1. JSON.stringify报cyclic object value错误

    这是一个典型的循环引用的错误,一个对象里引用自己就会立刻得到这个错误: obj = { x:555, y: "hi" }; obj.myself = obj; try{ json ...

  2. 【python】泰语分词器安装

    1.安装icu http://blog.csdn.net/liyuwenjing/article/details/6105388 2.安装pyicu https://anaconda.org/kale ...

  3. ABBYY FineReader操作技巧

    使用ABBYY FineReader OCR文字识别软件工作即快速又简单,软件自身常常可以自行处理一切工作,用户只需点击几下软件中的‘主要’按钮.不过,有时要想获得更好的质量结果,或者解决某个不寻常的 ...

  4. PyCharm搭建pyqt5开发环境

    PyCharm搭建PyQt5开发环境 1.安装PyQt5 2.PyCharm环境配置 2.1 添加QtDesigner 2.2 添加PyUIC 2.3 添加Pyrcc 2.4 添加assistant ...

  5. ios开发之--搜索框的使用(PYSearchViewController的使用)

    最近需要开发搜索框,比较了以前的各个版本的搜索框,UISearchDisplayController和UISearchController的使用,以后再做记录,随着ios11的更新,一些控件发生了,改 ...

  6. Code-audit-Learning

    代码审计精华文章收录: 关于php的一些'特性'或漏洞  https://github.com/80vul/phpcodz [干货分享]PHP漏洞挖掘——进阶篇    http://blog.nsfo ...

  7. 使用 requests 访问 HTTPS

    当我们访问 HTTPS 的网站时,需要进行证书验证,在浏览器中可以自动处理验证问题,在 Python 中有以下两种做法: import requests //不进行证书验证,但这种方式会出现警告,如下 ...

  8. Hashtable的应用

    一,哈希表(Hashtable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似key/value的键值对,其 ...

  9. 在recycler中写的布局不起作用

    把 LinearLayout 改成 RelativeLayout   ok了 创建的两种方式 1.LayoutInflater.from(parent.getContext()).inflate(R. ...

  10. linux 下 java 链接oracle数据库

    import java.sql.*; public class Hello { private final String oracleDriverName = "oracle.jdbc.dr ...