1. 程式人生 > >1001: [BeiJing2006]狼抓兔子 (最大流)

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

地形 opened har 分享 false led www getch data

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]狼抓兔子 (最大流)