首页 > 代码库 > BZOJ1001 [BeiJing2006]狼抓兔子

BZOJ1001 [BeiJing2006]狼抓兔子

题目

1001: [BeiJing2006]狼抓兔子

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 20245  Solved: 5038
[Submit][Status][Discuss]

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新加数据一组,可能会卡掉从前可以过的程序。

题解

一道模板题

以START点为源点,END为汇点

网格中的点为网络中的点

网格上的边位点之间的边建图

跑网络流就行了

附上满分代码

  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 } 

 

BZOJ1001 [BeiJing2006]狼抓兔子