题目描述

现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:

左上角点为(1,1),右下角点为(N,M)(上图中N=3,M=4).有以下三种类型的道路

1:(x,y)<==>(x+1,y)

2:(x,y)<==>(x,y+1)

3:(x,y)<==>(x+1,y+1)

道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下角(N,M)的窝中去,狼王开始伏击这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的狼的数量要最小。因为狼还要去找喜羊羊麻烦。

输入输出格式

输入格式:

第一行为N,M.表示网格的大小,N,M均小于等于1000.

接下来分三部分

第一部分共N行,每行M-1个数,表示横向道路的权值.

第二部分共N-1行,每行M个数,表示纵向道路的权值.

第三部分共N-1行,每行M-1个数,表示斜向道路的权值.

输出格式:

输出一个整数,表示参与伏击的狼的最小数量.

输入输出样例

输入样例#1:

3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6

输出样例#1:

14

思路:按照题目中所说的,见横向,纵向和沿对角线的边,题目显然是要我们求最小割,直接跑dinic求最大流就可以了。

代码:

#include<cstdio>
#include<cstring>
#include<cctype>
#include<queue>
#define maxn 2000007
#define inf 0x3f3f3f3f
using namespace std;
int n,m,S=1,T,head[maxn],num=1,d[maxn];
inline int qread() {
char c=getchar();int num=0,f=1;
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) num=num*10+c-'0';
return num*f;
}
struct node {
int v,w,nxt;
}e[6000007];
inline void ct(int u, int v, int w) {
e[++num].v=v;
e[num].w=w;
e[num].nxt=head[u];
head[u]=num;
}
inline bool bfs() {
memset(d,-1,sizeof(d));
queue<int>q;
q.push(S),d[S]=0;
while(!q.empty()) {
int u=q.front();
q.pop();
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(e[i].w&&d[v]==-1) {
d[v]=d[u]+1;
q.push(v);
}
}
}
return d[T]!=-1;
}
int dfs(int u, int f) {
if(u==T) return f;
int rest=f;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(d[v]==d[u]+1&&e[i].w&&rest) {
int t=dfs(v,min(e[i].w,rest));
if(!t) d[v]=0;
e[i].w-=t;
e[i^1].w+=t;
rest-=t;
}
}
return f-rest;
}
inline int dinic() {
int ans=0;
while(bfs()) ans+=dfs(S,inf);
return ans;
}
int main() {
n=qread(),m=qread();
T=n*m;
for(int i=1;i<=n;++i) {
int tmp=(i-1)*m;
for(int j=1,x;j<m;++j) {
x=qread();
ct(tmp+j,tmp+j+1,x),ct(tmp+1+j,tmp+j,x);
}
}
for(int i=1;i<n;++i) {
int tmp=(i-1)*m;
for(int j=1,x;j<=m;++j) {
x=qread();
ct(tmp+j,tmp+j+m,x),ct(tmp+j+m,tmp+j,x);
}
}
for(int i=1;i<n;++i) {
int tmp=(i-1)*m;
for(int j=1,x;j<m;++j) {
x=qread();
ct(tmp+j,tmp+m+j+1,x),ct(tmp+m+1+j,tmp+j,x);
}
}
printf("%d\n",dinic());
return 0;
}

最新文章

  1. 从头开始构建LINUX [LFS 脚本]
  2. 树型dp
  3. 如何做个简单安卓App流程
  4. PHP中的CURL函数库
  5. 【PDF】java使用Itext生成pdf文档--详解
  6. Entity Framework Code First级联删除
  7. Tomcat J2ee 发布步骤
  8. logback logback.xml 常用配置详解
  9. 推荐两个不错的CAD二次开发(.Net)手册
  10. Codeforces 474A Keyboard (水
  11. ROSCon 2016视频和幻灯片发布 ROS机器人操作系统重要参考资料
  12. Windows Server 安装后无法使用无线与音频
  13. vue学习笔记(二)- 数据绑定、列表渲染、条件判断
  14. 使用pm2离线部署nodejs项目
  15. spring框架排错
  16. window.location.replace()与window.location.href()区别
  17. 动手动脑-java重载
  18. win10家庭版升级专业版的两种方法和密钥
  19. 对微软Microsoft Dynamics CRM 的认识
  20. Python: attrgetter()函数: 排序不支持原生比较的对象

热门文章

  1. 【280】◀▶ ArcPy 常用工具说明
  2. 利用Sphinx编写文档
  3. Subscript &amp; Inheritance
  4. codeforce 457DIV2 C题
  5. 使用RandomAccessFile读写数据
  6. shell cut 用法
  7. InvocationtargetException 类型转换异常
  8. 38.NOW() 函数
  9. mysql for visual
  10. Office Web APP预览如何去掉顶部版权标志“Microsoft Office Web Apps”