BZOJ1001 BJOI2006 狼抓兔子

Description


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

左上角点为(1,1),右下角点为(N,M)(上图中N=3,M=4).有以下三种类型的道路

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个数,表示斜向道路的权值.

Output:

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

Solution

转化为网络流,把每个有直接连边的点之间连一条权为X的边,然后跑一边最大流即可。

 1 //Writer : Hsz %WJMZBMR%tourist%hzwer
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 #include<map>
 8 #include<set>
 9 #include<stack>
10 #include<vector>
11 #include<cstdlib>
12 #include<algorithm>
13 #define LL long long
14 using namespace std;
15 const int S=1,N=1000001,M=6000001,inf=0x3fffffff;
16 int to[M],val[M],nxt[M],h[N],head[N],ecnt=1,T;
17 int n,m;
18 void add(int bg,int ed,int v) {
19     to[++ecnt]=ed;
20     nxt[ecnt]=head[bg];
21     val[ecnt]=v;
22     head[bg]=ecnt;
23 }
24 void ins(int bg,int ed,int x) {
25     add(bg,ed,x);
26     add(ed,bg,x);
27 }
28 bool bfs() {
29     memset(h,-1,sizeof h);
30     h[S]=0;
31     queue<int>q;
32     q.push(S);
33     while(!q.empty()) {
34         int u=q.front();
35         q.pop();
36         for(int i=head[u]; i; i=nxt[i]) {
37             if(val[i]&&h[to[i]]==-1) {
38                 h[to[i]]=h[u]+1;
39                 q.push(to[i]);
40             }
41         }
42     }
43     return h[T]!=-1;
44 }
45 int dfs(int x,int f) {
46     if(x==T) return f;
47     int tp,used=0;
48     for(int i=head[x]; i; i=nxt[i]) {
49         if(h[to[i]]==h[x]+1&&val[i]) {
50             tp=dfs(to[i],min(f-used,val[i]));
51             val[i]-=tp;
52             val[i^1]+=tp;
53             used+=tp;
54             if(used==f) return f;
55         }
56     }
57     if(!used ) h[x]=-1;
58     return used;
59 }
60 int maxflow;
61 void dinic() {
62     maxflow=0;
63     while(bfs()) {
64         maxflow+=dfs(1,inf);
65     }
66 }
67 int main() {
68     int x;
69     cin>>n>>m;
70     T=n*m;
71     for(int i=1; i<=n; i++) {
72         for(int j=1; j<m; j++) {
73             scanf("%d",&x);
74             ins(m*(i-1)+j,m*(i-1)+j+1,x);//建图过程。加的反边也应权为x,因为反向也可能跑兔子。
75         }
76     }
77     for(int i=1; i<n; i++) {
78         for(int j=1; j<=m; j++) {
79             scanf("%d",&x);
80             ins(m*(i-1)+j,m*(i)+j,x);
81         }
82     }
83     for(int i=1; i<n; i++) {
84         for(int j=1; j<m; j++) {
85             scanf("%d",&x);
86             ins(m*(i-1)+j,m*(i)+j+1,x);
87         }
88     }
89     dinic();
90     cout<<maxflow;
91     return 0;
92 }

 

posted @ 2018-05-08 00:11  SWHsz  阅读(152)  评论(0编辑  收藏  举报