1001. [BJOI2006]狼抓兔子【最小割】

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
 
比较裸的一个题,记得建立双向边
建立双向变有个小技巧,就是正反边流量都为正数
 
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 #define N (2000000+10)
 6 using namespace std;
 7 struct node
 8 {
 9     int to,next,Flow;
10 }edge[N<<2];
11 int n,m,x,s,e;
12 int head[N],num_edge;
13 int Depth[N]; 
14 queue<int>q;
15 
16 void add(int u,int v,int l)
17 {
18     edge[++num_edge].to=v;
19     edge[num_edge].Flow=l;
20     edge[num_edge].next=head[u];
21     head[u]=num_edge;
22 }
23 
24 bool Bfs(int s,int e)
25 {
26     memset(Depth,0,sizeof(Depth));
27     Depth[s]=1;
28     q.push(s);
29     while (!q.empty())
30     {
31         int x=q.front();
32         q.pop();
33         for (int i=head[x];i!=0;i=edge[i].next)
34             if (!Depth[edge[i].to] && edge[i].Flow>0)
35             {
36                 Depth[edge[i].to]=Depth[x]+1;
37                 q.push(edge[i].to);
38             }
39     }
40     return Depth[e]!=0;
41 }
42 
43 int Dfs(int x,int low)
44 {
45     int Min,f=0;
46     if (x==e || low==0)    return low;
47     for (int i=head[x];i!=0;i=edge[i].next)
48         if (edge[i].Flow>0 && Depth[edge[i].to]==Depth[x]+1 && (Min=Dfs(edge[i].to,min(edge[i].Flow,low))))
49         {
50             edge[i].Flow-=Min;
51             edge[((i-1)^1)+1].Flow+=Min;
52             f+=Min;
53             low-=Min;
54             if (low==0) return f;
55         }
56     if (f==0) Depth[x]=0;
57     return f;
58 }
59 
60 int Dinic(int s,int e)
61 {
62     int Ans=0;
63     while (Bfs(s,e))
64         Ans+=Dfs(s,0x7fffffff);
65     return Ans;
66 }
67 
68 int main()
69 {
70     scanf("%d%d",&n,&m);//n行m列 
71     s=1,e=n*m;
72     for (int i=1;i<=n;++i)
73         for (int j=1;j<=m-1;++j)
74         {
75         
76             scanf("%d",&x);
77             add((i-1)*m+j,(i-1)*m+j+1,x);
78             add((i-1)*m+j+1,(i-1)*m+j,x);
79         }
80     for (int i=1;i<=n-1;++i)
81         for (int j=1;j<=m;++j)
82         {
83             scanf("%d",&x);
84             add((i-1)*m+j,i*m+j,x);
85             add(i*m+j,(i-1)*m+j,x);
86         }
87     for (int i=1;i<=n-1;++i)
88         for (int j=1;j<=m-1;++j)
89         {
90             scanf("%d",&x);
91             add((i-1)*m+j,i*m+j+1,x);
92             add(i*m+j+1,(i-1)*m+j,x);
93         }
94     printf("%d",Dinic(s,e));
95 }
posted @ 2018-03-31 07:13  Refun  阅读(176)  评论(0编辑  收藏  举报