现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,
而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(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只狼,
才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
狼的数量要最小。因为狼还要去找喜羊羊麻烦.
第一行为N,M.表示网格的大小,N,M均小于等于1000.
接下来分三部分
第一部分共N行,每行M-1个数,表示横向道路的权值.
第二部分共N-1行,每行M个数,表示纵向道路的权值.
第三部分共N-1行,每行M-1个数,表示斜向道路的权值.
输入文件保证不超过10M
1 /**************************************************************
2 Problem: 1001
3 User: q747841082
4 Language: C++
5 Result: Accepted
6 Time:2056 ms
7 Memory:83324 kb
8 ****************************************************************/
9
10 #include <iostream>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 using namespace std;
15 const int inf=0x3f3f3f;
16
17 struct edge
18 {
19 int next,v,to;
20 }e[6000005];
21
22 int head[1000005];
23 int n,m,s,t,cnt=1;
24 long long ans=0;
25 int h[1000005],q[1000005];
26
27 void addedge(int x,int y,int w)//因为原图为无向图,所以反向边权值可直接设为w
28 {
29 e[++cnt].to=y;e[cnt].next=head[x];head[x]=cnt;e[cnt].v=w;
30 e[++cnt].to=x;e[cnt].next=head[y];head[y]=cnt;e[cnt].v=w;
31 }//还避免了边数加倍(原本每条边都需加一条权值为0的反向边),减小了时间、空间的复杂度
32
33 bool bfs()
34 {
35 int he=0,tail=1,now;
36 for(int i=0;i<=t;i++)
37 h[i]=-1;
38 q[0]=s;h[s]=0;
39 while(he!=tail)
40 {
41 now=q[he];
42 he++;
43 for(int i=head[now];i!=-1;i=e[i].next)
44 if(e[i].v&&h[e[i].to]==-1)
45 {
46 h[e[i].to]=h[now]+1;
47 q[tail++]=e[i].to;
48 }
49 }
50 return h[t]!=-1;
51 }
52
53 int dfs(int x,int f)
54 {
55 if(x==t)
56 return f;
57 int w,used=0;
58 for(int i=head[x];i!=-1;i=e[i].next)
59 if(h[e[i].to]==h[x]+1)
60 {
61 w=f-used;
62 w=dfs(e[i].to,min(w,e[i].v));
63 e[i].v-=w;e[i^1].v+=w;
64 used+=w;
65 if(used==f)
66 return f;
67 }
68 if(!used) h[x]=-1;
69 return used;
70 }
71
72 void Dinic()
73 {
74 while(bfs())
75 ans+=dfs(s,inf);
76 }
77
78 int main()
79 {
80 int w,i,j;
81 scanf("%d %d",&n,&m);
82 memset(head,-1,sizeof(head));
83 s=1;t=n*m;
84 for(i=1;i<=n;i++)
85 for(j=1;j<=m-1;j++)
86 {
87 scanf("%d",&w);
88 addedge((i-1)*m+j,(i-1)*m+j+1,w);
89 }
90 for(i=1;i<=n-1;i++)
91 for(j=1;j<=m;j++)
92 {
93 scanf("%d",&w);
94 addedge((i-1)*m+j,i*m+j,w);
95 }
96 for(i=1;i<=n-1;i++)
97 for(j=1;j<=m-1;j++)
98 {
99 scanf("%d",&w);
100 addedge((i-1)*m+j,i*m+j+1,w);
101 }
102 Dinic();
103 printf("%lld\n",ans);
104 return 0;
105 }