bzoj1001 [BeiJing2006]狼抓兔子

题目

不能让狼去终点,代价最小。。
又是一道最小割。

第一道最小割,记录一下。

不过模板写的真的丑233。

#include<bits/stdc++.h>
#define MAXN 1000001
#define id(i,j) (i-1)*m+j
using namespace std;
int first[1000001],nex[6*MAXN+1],to[6*MAXN+1],cap[6*MAXN+1],flow[6*MAXN+1],size;
int dis[1000001];
int n,m;
int Q[1001001],l,r;
long long Ans;
bool E[1000001];
void init()
{
    memset(first,-1,sizeof(first));
}
void add(int x,int y,int ca)
{
    nex[size]=first[x];
    first[x]=size;
    to[size]=y;
    cap[size]=ca;
    size++;
    nex[size]=first[y];
    first[y]=size;
    to[size]=x;
    cap[size]=ca;
    size++;

}
bool BFS()
{
    Q[1]=1,l=0,r=1;
    dis[1]=0;
    memset(E,false,sizeof(E));
    E[1]=true;
    while(l<r)
    {
        int x=Q[++l];
        for(int i=first[x];i!=-1;i=nex[i])
        {
            int u=to[i];
            if(!E[u]&&cap[i]>flow[i])
            {
                Q[++r]=u;
                E[u]=true;
                dis[u]=dis[x]+1;
            }
        }
    }
    return E[m*n];
}
int DFS(int s,int a)
{
    if(s==m*n||a==0)return a;
    int fl=0,f;
    for(int i=first[s];i!=-1;i=nex[i])
    {
        int u=to[i];
        if(dis[u]==dis[s]+1&&(f=DFS(u,min(a,cap[i]-flow[i])))>0)
        {
            flow[i]+=f;
            flow[i^1]-=f;
            fl+=f;
            a-=f;
            if(a==0)break;
        }
    }
    if(!fl)dis[s]=-2;
    return fl;
}
void get_map()
{
    int x;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<m;j++)
        {
            scanf("%d",&x);
            add(id(i,j),id(i,j+1),x);
        }
    }
    for(int i=1;i<n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&x);
            add(id(i,j),id(i+1,j),x);
        }
    }
    for(int i=1;i<n;i++)
    {
        for(int j=1;j<m;j++)
        {
            scanf("%d",&x);
            add(id(i,j),id(i+1,j+1),x);
        }
    }   
}
int main()
{
    init();
    scanf("%d%d",&n,&m);    
    get_map();
//  for(int i=1;i<=m*n;i++)
//  {
//      cout<<i<<":\n";
//      for(int j=first[i];j!=-1;j=nex[j])
//          cout<<to[j]<<" "<<cap[j]<<endl;
//      cout<<endl;
//  }
    Ans=0;
    while(BFS()){Ans+=DFS(1,~0u>>1);}
    cout<<Ans;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值