1001: [BeiJing2006]狼抓兔子

1001: [BeiJing2006]狼抓兔子

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 12827  Solved: 3044
[Submit][Status][Discuss]

Description

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

 1001: [BeiJing2006]狼抓兔子

左上角点为(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为源点,以m*n为汇点用Dinic跑一遍最大流即可,其中要注意由于题目中说了是无向边所以加边的时候要注意正向反向的边的权值要一样。

  下面是我用Dinic写的,并没有AC,原因在于当n和m大于300时读入会崩溃,变成RE,用对拍随机了几组n,m为100左右的数据都能过,说明整体思路是可行的(m,n太大下面再说用最短路的方法),求大神帮我看看错哪了。

 

  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 }

 

你可能感兴趣的:(in)