【bzoj3774】【最优选择】【最小割】
2016-07-01 11:28
323 查看
Description
小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择了的。一个点如果被选择了,那么可以得到Bij的回报,现在请你帮小N选一个最优的方案,使得回报-代价尽可能大。Input
第一行两个正整数N,M表示方格图的长与宽。接下来N行每行M个整数Aij表示控制的代价。
接下来N行每行M个整数Bij表示选择的回报。
Output
一个整数,表示最大的回报-代价(如果一个都不控制那么就是0)。Sample Input
3 31 100 100
100 1 100
1 100 100
2 0 0
5 2 0
2 0 0
Sample Output
8HINT
对于100%的数据,N,M<=50,Aij,Bij都是小于等于100的正整数。题解:
首先我们可以发现如果选了周围四个点那一定不会选中间这个点,
这样我们就可以把方案变成两种:
1.选中间的点,
2.选四周的点,不选中间的点.
这很像文理分科,唯一不一样的地方在于一种限制里面选和不选都有.
所以我们可以对矩阵黑白染色,让白点和黑点的源汇意义相反.然后就可以用文理分科的方法做了.
代码:
#include<iostream> #include<cstdio> #include<cstring> #define N 6000 #define M 300000 #define inf 210000000 using namespace std; int x,n,m,T,ans,point ,next[M<<1],cnt=1,dx[]={1,0,-1,0},dy[]={0,1,0,-1}; int cur ,pre ,dis ,gap ; struct use{ int st,en,v; }e[M<<1]; int read(){ int x(0);char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x; } void add(int x,int y,int v){ next[++cnt]=point[x];point[x]=cnt; e[cnt].st=x;e[cnt].en=y;e[cnt].v=v; next[++cnt]=point[y];point[y]=cnt; e[cnt].st=y;e[cnt].en=x;e[cnt].v=0; } int cal(int x,int y){return (x-1)*m+y;} int isap(){ int mn,i,u(1),ans(0);gap[0]=T; for (int i=1;i<=T;i++) cur[i]=point[i]; while (dis[1]<T){ bool f=false; for (i=cur[u];i;i=next[i]) if (e[i].v&&dis[u]==dis[e[i].en]+1){f=true;cur[u]=i;break;} if (f){ pre[u=e[i].en]=i; if (u==T){ mn=inf; for (int i=T;i!=1;i=e[pre[i]].st) mn=min(mn,e[pre[i]].v); ans+=mn; for (int i=T;i!=1;i=e[pre[i]].st) e[pre[i]].v-=mn,e[pre[i]^1].v+=mn; u=1; } } else{ gap[dis[u]]--;if (!gap[dis[u]]) return ans; for (mn=T,i=point[u];i;i=next[i]) if (e[i].v) mn=min(mn,dis[e[i].en]); gap[dis[u]=mn+1]++;cur[u]=point[u];if (u!=1) u=e[pre[u]].st; } } return ans; } int main(){ n=read();m=read();T=n*m+n*m+2; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++){ x=read(); if (i+j&1) add(1,cal(i,j)+1,x); else add(cal(i,j)+1,T,x); } for (int i=1;i<=n;i++) for (int j=1;j<=m;j++){ x=read();ans+=x+x; if (i+j&1){ add(cal(i,j)+1,T,x); add(1,cal(i,j)+1+n*m,x); add(cal(i,j)+1+n*m,cal(i,j)+1,inf); for(int k=0;k<4;k++){ int xx=i+dx[k],yy=j+dy[k]; if (xx<1||xx>n||yy<1||yy>m) continue; add(cal(i,j)+1+n*m,cal(xx,yy)+1,inf); } } else{ add(1,cal(i,j)+1,x); add(cal(i,j)+1+n*m,T,x); add(cal(i,j)+1,cal(i,j)+1+n*m,inf); for (int k=0;k<4;k++){ int xx=i+dx[k],yy=j+dy[k]; if (xx<1||xx>n||yy<1||yy>m) continue; add(cal(xx,yy)+1,cal(i,j)+1+n*m,inf); } } } ans-=isap(); cout<<ans<<endl; }
相关文章推荐
- Tomcat配置加密
- java编程相关总结(四)
- java数组浅谈
- Java SE-表达式、块、流程控制
- JavaGUI版本销售管理系统
- 了解一下Logstash
- LeetCode 371 Sum of Two Integers
- Editplus批量修改编码格式
- linux压缩解压文件
- PHP日期时间函数之strtotime()
- SD-关于信用释放时的ATP检查的逻辑(note:1324433)
- 如何生成能在没有安装opencv库及vs2010环境的电脑上运行的exe文件
- Import Statements 导入语句
- 浅析渲染性能(转)
- Android组件化和插件化开发
- 雷洋案尸检结果公布 你是否发现社会已悄然改变
- unsetenv
- HDU——1242Rescue(BFS+优先队列求点图最短路)
- UIBezierPath精讲
- Toolbar+DrawerLayout高仿网易新闻客户端