BZOJ 1001[BeiJing2006]狼抓兔子 (网络流 Dinic)

来源:互联网 发布:美漫长相知乎 编辑:程序博客网 时间:2024/06/03 04:08

1001: [BeiJing2006]狼抓兔子

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 24061  Solved: 6086
[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


Dinic 网络流;

套模板, 此模板 已经优化过了, 所以不会超时;

源点 start  汇点 END


代码:

#include <iostream>#include <stdio.h>#include <algorithm>#include <math.h>#include <cmath>#include <cstring>#include <string>#include <queue>#include <stack>#include <stdlib.h>#include <list>#include <map>#include <set>#include <bitset>#include <vector>#define mem(a,b) memset(a,b,sizeof(a))#define findx(x) lower_bound(b+1,b+1+bn,x)-b#define FIN      freopen("input.txt","r",stdin)#define FOUT     freopen("output.txt","w",stdout)#define S1(n)    scanf("%d",&n)#define SL1(n)   scanf("%I64d",&n)#define S2(n,m)  scanf("%d%d",&n,&m)#define SL2(n,m)  scanf("%I64d%I64d",&n,&m)#define Pr(n)     printf("%d\n",n)using namespace std;typedef long long ll;const int INF=0x3f3f3f3f;const double esp=1e-6;const int maxn=1e6+5;const int MOD=1e9+7;const int mod=1e9+7;int dir[5][2]={0,1,0,-1,1,0,-1,0};struct node{    int v,w,next; //u  v 从 u-v 权值为w}edge[8*maxn];int head[maxn],num[maxn],start,END,cnt,sum;int n,m;void init(){    cnt=0;    mem(head,-1);}void add(int u,int v,int w){    edge[cnt].v=v;    edge[cnt].w=w;    edge[cnt].next=head[u];    head[u]=cnt++;    /*edge[cnt].v=u;    edge[cnt].w=0;    edge[cnt].next=head[v];    head[v]=cnt++;    */}int bfs(){    queue<int>Q;    mem(num,0);    num[start]=1;    Q.push(start);    while(!Q.empty())    {        int t=Q.front();        Q.pop();        if(t==END)            return 1;        for(int i=head[t];i!=-1;i=edge[i].next)// 链式前向星访问找增广路        {            int t1= edge[i].v;//下一个节点            int t2= edge[i].w;// 当前点 权值            if(t2&&num[t1]==0)// 当前点存在 并且下一个点没有访问            {                num[t1]=num[t]+1;// 点=1                if(t1==END)//  结束                    return 1;                Q.push(t1);            }        }    }    return 0;}int dfs(int u,int maxflow){    if(u==END)        return maxflow;    int res=0;    for(int i=head[u];i!=-1;i=edge[i].next)    {        int t1=edge[i].v;// 下一个节点        int t2=edge[i].w;// 当前节点        if(t2&&num[t1]==num[u]+1)        {            int temp=dfs(t1,min(maxflow-res,t2));// 选择流 小的一部分            edge[i].w-=temp;// 正向减少            edge[i^1].w+=temp;//反向增加            res+=temp;            if(maxflow==res)                return res;        }    }    if(!res)        num[u]=-1;    return res;}void Dinic(){    int ans=0;    while(bfs())    {        ans+=dfs(start,INF);    }    cout<<ans<<endl;}int main(){    while(~S2(n,m))    {        init();        int x,y;        int cost;        start=1;        END=n*m;        for(int i=0;i<n;i++)// 横            for(int j=1;j<=m-1;j++)            {                S1(cost);                x= i*m+j;                y= x+1;                add(x,y,cost);                add(y,x,cost);            }        for(int i=0;i<n-1;i++)//列            for(int j=1;j<=m;j++)            {                S1(cost);                x= i*m+j;                y= x+m;                add(x,y,cost);                add(y,x,cost);            }        for(int i=0;i<n-1;i++)// 斜            for(int j=1;j<=m-1;j++)            {                S1(cost);                x= i*m+j;                y= x+m+1;                add(x,y,cost);                add(y,x,cost);            }        Dinic();    }    return 0;}/*3 45 6 44 3 17 5 35 6 7 88 7 6 55 5 56 6 6*/


123

原创粉丝点击