现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(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 #include<cstdio>
2 #include<cstdlib>
3 #include<iostream>
4 #include<cmath>
5 #include<algorithm>
6 #include<queue>
7 #include<stack>
8 #include<map>
9 using namespace std;
10 const int N=5000;
11 const int M=5000*5;
12 const int inf=1e9;
13 struct Edge{//链表存图
14 int to;
15 int rest;
16 int next;
17 };
18 Edge E[M];
19 int head[N],ecnt=1;
20
21 inline void AddEdge(int x,int y,int z){//加边
22 ecnt++; E[ecnt].to=y; E[ecnt].rest=z; E[ecnt].next=head[x]; head[x]=ecnt;
23 ecnt++; E[ecnt].to=x; E[ecnt].rest=z; E[ecnt].next=head[y]; head[y]=ecnt;
24 }
25 int n,m,S,T;
26 int tot;
27 int dis[N];
28
29 inline bool BFS(){
30 static queue<int> Q;
31 for(int i=S;i<=T;i++) dis[i]=-1;
32 Q.push(S);
33 dis[S]=0;
34 while(!Q.empty()){
35 int x=Q.front(); Q.pop();
36 for(int e=head[x];e;e=E[e].next){
37 if(E[e].rest&&dis[E[e].to]==-1){
38 dis[E[e].to]=dis[x]+1;
39 Q.push(E[e].to);
40 }
41 }
42 }
43 return dis[T]>-1;
44 }
45 inline int DFS(int x,int flow){
46 if(x==T) return flow;
47 int a=0,b;
48 for(int e=head[x];e;e=E[e].next){
49 if(E[e].rest!=0&&dis[E[e].to]==dis[x]+1){
50 b=DFS(E[e].to,min(flow-a,E[e].rest));
51 E[e].rest-=b;
52 E[e^1].rest+=b;
53 a+=b;
54 if(a==flow)
55 return flow;
56 }
57 }
58 if(a==0) dis[x]=-1;
59 return a;
60
61 }
62 inline int dinic(){
63 int ans = 0;
64 while(BFS()==true)
65 ans += DFS(S, inf);
66 return ans;
67 }
68 int main(){
69 scanf("%d%d",&n,&m);
70 int tot=n*m;
71 S=1; T=tot;
72 int c;
73 //构图
74 for(int i=1;i<=n;i++){
75 for(int j=1;j<=m-1;j++){
76 int l=(i-1)*m+j;
77 int r=(i-1)*m+j+1;
78 scanf("%d",&c);
79 AddEdge(l,r,c);
80 }
81 }
82 for(int i=1;i<=n-1;i++){
83 for(int j=1;j<=m;j++){
84 int up=(i-1)*m+j;
85 int down=up+m;
86 scanf("%d",&c);
87 AddEdge(up,down,c);
88 }
89 }
90 for(int i=1;i<=n-1;i++){
91 for(int j=1;j<=m-1;j++){
92 int lu=(i-1)*m+j;
93 int rd=lu+m+1;
94 scanf("%d",&c);
95 AddEdge(lu,rd,c);
96 }
97 }
98 //构图结束
99 printf("%d\n", dinic());
100
101 return 0;
102 }