首页 > 代码库 > 1001: [BeiJing2006]狼抓兔子 (最大流)

1001: [BeiJing2006]狼抓兔子 (最大流)

Description

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

 技术分享

左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 
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只狼,
才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
狼的数量要最小。因为狼还要去找喜羊羊麻烦.

Input

第一行为N,M.表示网格的大小,N,M均小于等于1000.
接下来分三部分
第一部分共N行,每行M-1个数,表示横向道路的权值. 
第二部分共N-1行,每行M个数,表示纵向道路的权值. 
第三部分共N-1行,每行M-1个数,表示斜向道路的权值. 
输入文件保证不超过10M

Output

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

Sample Input

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

Sample Output

14

HINT

 

 2015.4.16新加数据一组,可能会卡掉从前可以过的程序。

 

Source

 

技术分享
  1 /*  2     dinic 模板   3 */  4 #include<queue>  5 #include<cstdio>  6 #include<iostream>  7 #define MAXN 1000010  8   9 using namespace std; 10  11 int depth[MAXN],cur[MAXN]; 12  13 int n,m,val,s,t,ans; 14  15 struct node { 16     int to; 17     int next; 18     int val; 19 };  20 node e[MAXN*6]; 21  22 int head[MAXN*6],tot=1; 23  24 queue<int> q; 25  26 inline void read(int&x) { 27     int f=1;x=0;char c=getchar(); 28     while(c>9||c<0) {if(c==-) f=-1;c=getchar();} 29     while(c>=0&&c<=9) {x=(x<<1)+(x<<3)+c-48;c=getchar();} 30     x=x*f; 31 } 32  33 inline void add(int x,int y,int v) { 34     e[++tot].to=y; 35     e[tot].val=v; 36     e[tot].next=head[x]; 37     head[x]=tot; 38 } 39  40 inline int qu(int x,int y) { 41     return x*m+y; 42 }  43  44 inline bool bfs() { 45     for(int i=0;i<=t;i++) cur[i]=head[i],depth[i]=-1; 46     while(!q.empty()) q.pop(); 47     q.push(s);depth[s]=0; 48     while(!q.empty()) { 49         int now=q.front(); 50         q.pop(); 51         for(int i=head[now];i!=0;i=e[i].next) { 52             int to=e[i].to; 53             if(e[i].val>0&&depth[to]==-1) { 54                 q.push(to); 55                 depth[to]=depth[now]+1; 56                 if(to==t) return true;  57             } 58         } 59     } 60     return false; 61 } 62  63 inline int dinic(int now,int flow) { 64     if(now==t) return flow; 65     int delat,rest=0; 66     for(int i=head[now];i!=0;i=e[i].next) { 67         int to=e[i].to; 68         if(depth[to]==depth[now]+1&&e[i].val>0) { 69             delat=dinic(to,min(e[i].val,flow-rest)); 70             if(delat) { 71                 e[i].val-=delat; 72                 e[i^1].val+=delat; 73                 rest+=delat; 74                 if(rest==flow) break; 75             } 76         } 77     } 78     if(rest!=flow) depth[now]=-1; 79     return rest; 80 } 81  82 int main() { 83     read(n);read(m); 84     for(int i=1;i<=n;i++) 85       for(int j=1;j<m;j++) { 86             read(val); 87           add(qu(i-1,j),qu(i-1,j)+1,val); 88           add(qu(i-1,j)+1,qu(i-1,j),val); 89       } 90     for(int i=1;i<n;i++) 91       for(int j=1;j<=m;j++) { 92           read(val); 93           add(qu(i-1,j),qu(i,j),val); 94           add(qu(i,j),qu(i-1,j),val); 95       } 96     for(int i=1;i<n;i++) 97       for(int j=1;j<m;j++) { 98           read(val); 99           add(qu(i-1,j),qu(i,j)+1,val);100           add(qu(i,j)+1,qu(i-1,j),val);101       }102     t=n*m+1;103     add(s,1,0x7fffffff);104     add(t-1,t,0x7fffffff);105     while(bfs())106       ans+=dinic(s,0x7fffffff);107     printf("%d\n",ans);108     return 0;109 } 
代码

 

1001: [BeiJing2006]狼抓兔子 (最大流)