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

bzoj1001 [BeiJing2006]狼抓兔子

 

1001: [BeiJing2006]狼抓兔子

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 12749  Solved: 3027
[Submit][Status][Discuss]

Description

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

 <iframe id="iframe_0.585232120747647" src="data:text/html;charset=utf8,%3Cstyle%3Ebody%7Bmargin:0;padding:0%7D%3C/style%3E%3Cimg%20id=%22img%22%20src=%22http://www.lydsy.com/JudgeOnline/images/1001.jpg?_=4634143%22%20style=%22border:none;max-width:696px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById(‘img‘);%20window.parent.postMessage(%7BiframeId:‘iframe_0.585232120747647‘,width:img.width,height:img.height%7D,%20‘http://www.cnblogs.com‘);%7D%3C/script%3E" frameborder="0" scrolling="no" width="320" height="240"></iframe>

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

 

Source

其实dinic可以过

flag 今天起手写循环队列

#include<cstdio>#include<cstring>#include<queue>#include<cstdlib> #define MAXN 1000005#define INF 0x3f3f3f3fusing namespace std; struct Edge{        int v,next,val;};Edge edge[6*MAXN]; int ggd=INF;int cycle,n,m,x,now,head[MAXN*6],s,t,dist[MAXN*6],vis[MAXN*6]; void addEdge(int u,int v,int val){        now++;        edge[now].v=v;        edge[now].next=head[u];        edge[now].val=val;        head[u]=now;} void init1(){        for (int i=1;i<=n;i++)        for (int j=1;j<=m-1;j++)        {                scanf("%d",&x),ggd=min(ggd,x);                if (i==1) { addEdge(t,(i-1)*cycle+j*2,x); addEdge((i-1)*cycle+j*2,t,x); }                else if (i==n) { addEdge((i-2)*cycle+j*2-1,s,x); addEdge(s,(i-2)*cycle+j*2-1,x); }                else { addEdge((i-2)*cycle+j*2-1,(i-1)*cycle+j*2,x); addEdge((i-1)*cycle+j*2,(i-2)*cycle+j*2-1,x); }        }} void init2(){        for (int i=1;i<=n-1;i++)        for (int j=1;j<=m;j++)        {                scanf("%d",&x),ggd=min(ggd,x);                if (j==1) { addEdge(s,(i-1)*cycle+1,x); addEdge((i-1)*cycle+1,s,x); }                else if (j==m) { addEdge(i*cycle,t,x); addEdge(t,i*cycle,x); }                else { addEdge((i-1)*cycle+j*2-2,(i-1)*cycle+j*2-1,x); addEdge((i-1)*cycle+j*2-1,(i-1)*cycle+j*2-2,x); }        } } void init3(){        int tot=-1;        for (int i=1;i<=n-1;i++)                for (int j=1;j<=m-1;j++)                {                        scanf("%d",&x); tot+=2,ggd=min(ggd,x);                        addEdge(tot,tot+1,x); addEdge(tot+1,tot,x);                }} void init(){        scanf("%d %d",&n,&m);        cycle=(m-1)*2;        s=(n-1)*(m-1)*2+1,t=s+1;        init1();         init2();         init3();        if(n==1||m==1){ printf("%d",ggd); exit(0);  }} struct state{        int num,nowVal;        state() {}        state(int _num,int _nowVal):num(_num),nowVal(_nowVal) {}        friend bool operator < (state a,state b) { return a.nowVal>b.nowVal; }}; priority_queue q; int Dijkstra(){        memset(dist,INF,sizeof(dist));        q.push(state(s,0));        dist[s]=0,vis[s]=0;        while (q.size())        {                state temp=q.top(); q.pop();                if (temp.nowVal>dist[temp.num]) continue;                if (temp.num==t) return dist[t];                 for (int x=head[temp.num];x!=0;x=edge[x].next)                {                        if (dist[temp.num]+edge[x].val                        {                                dist[edge[x].v]=dist[temp.num]+edge[x].val;                                q.push(state(edge[x].v,dist[edge[x].v]));                        }                }        }        return -1;} int main(){        init();        printf("%d",Dijkstra());        return 0;}

 

 

也可以对偶图+spfa

用切遍的代价为权值建图,最后联向超级源点和超级汇点

#include<iostream>#include<cstring>#include<cstdio>using namespace std;int n,m;int num;struct data{int v,next,w;}edge[6000001];int dis[1000001];int head[1000001],q[1000001],ans;void add_edge(int u,int v,int w){    num++;  edge[num].v=v;edge[num].w=w;edge[num].next=dis[u];dis[u]=num;}bool bfs(){    int now,i;    memset(head,-1,sizeof(head));    int t=0,w=1;    q[t]=1;head[1]=0;    while(t<w)    {           now=q[t];t++;        i=dis[now];        for(int i=dis[now];i;i=edge[i].next)                {            if(edge[i].w&&head[edge[i].v]<0)            {                q[w++]=edge[i].v;                head[edge[i].v]=head[now]+1;                             }        }    }    if(head[n*m]==-1)return 0;    return 1;}int dfs(int x,int f){    if(x==n*m)return f;    int i=dis[x];    int w,used=0;    while(i)    {        if(edge[i].v&&head[edge[i].v]==head[x]+1)        {            w=f-used;            w=dfs(edge[i].v,min(w,edge[i].w));            edge[i].w-=w;            edge[i+1].w+=w;            used+=w;            if(used==f)return f;        }        i=edge[i].next;    }    if(!used)head[x]=-1;    return used;}void dinic(){    while(bfs())ans+=dfs(1,0x7fffffff);}inline void init1(){    int x;     for(int i=1;i<=n;i++)        for(int j=1;j<m;j++)        {            scanf("%d",&x);            add_edge(m*(i-1)+j,m*(i-1)+j+1,x);            add_edge(m*(i-1)+j+1,m*(i-1)+j,x);        }}inline void init2(){    int x;    for(int i=1;i<n;i++)        for(int j=1;j<=m;j++)        {            scanf("%d",&x);            add_edge(m*(i-1)+j,m*(i)+j,x);            add_edge(m*(i)+j,m*(i-1)+j,x);        }}inline void init3(){    int x;    for(int i=1;i<n;i++)        for(int j=1;j<m;j++)        {            scanf("%d",&x);            add_edge(m*(i-1)+j,m*(i)+j+1,x);            add_edge(m*(i)+j+1,m*(i-1)+j,x);        }}inline void init(){    init1();    init2();    init3();}int main(){    scanf("%d%d",&n,&m);    init();    dinic();    printf("%d\n",ans);    return 0;}

 

bzoj1001 [BeiJing2006]狼抓兔子