1001: [BeiJing2006]狼抓兔子

/**************************************************************
    Problem: 1001
    User: whymhe
    Language: C++
    Result: Accepted
    Time:1236 ms
    Memory:106760 kb
****************************************************************/
 
//Pro:P4001 [BJOI2006]狼抓兔子
 
//大概就是求个最小割
//这个题的唯一的难点大概就是如何给网格图编号 
 
//一个比较坑的地方:
//边都是双向的,所以正反向弧的容量都是flow 
 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
 
inline int read()
{
    char c=getchar();int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num; 
}
 
const int N=1e6+5;
 
int n,m,S,T;
int head[N],num_edge;
struct Edge
{
    int v,flow,nxt;
}edge[N<<3];
 
inline void add_edge(int u,int v,int flow)
{
    edge[++num_edge].v=v;
    edge[num_edge].flow=flow;
    edge[num_edge].nxt=head[u];
    head[u]=num_edge;
}
 
int from[N],dep[N];
inline bool bfs()
{
    queue<int> que;
    int now;
    for(now=S;now<=T;++now)
        dep[now]=0,from[now]=head[now];
    que.push(S),dep[S]=1;
    while(!que.empty())
    {
        now=que.front(),que.pop();
        for(int i=head[now],v;i;i=edge[i].nxt)
        {
            v=edge[i].v;
            if(dep[v]||!edge[i].flow)
                continue;
            dep[v]=dep[now]+1;
            if(v==T)
                return 1;
            que.push(v);
        }
    }
    return 0;
}
 
int dfs(int u,int flow)
{
    if(u==T||!flow)
        return flow;
    int outflow=0,tmp;
    for(int &i=from[u],v;i;i=edge[i].nxt)
    {
        v=edge[i].v;
        if(dep[v]!=dep[u]+1)
            continue;
        tmp=dfs(v,min(flow,edge[i].flow));
        if(!tmp)
            continue;
        flow-=tmp;
        outflow+=tmp;
        edge[i].flow-=tmp;
        edge[i^1].flow+=tmp;
        if(!flow)
            return outflow;
    }
    dep[u]=0;
    return outflow;
}
 
int main()
{
    num_edge=1;
    n=read(),m=read();
    S=1,T=n*m;
    for(int i=1,p,f;i<=n;++i)
    {
        for(int j=1;j<m;++j)
        {
            p=(i-1)*m+j;
            f=read();
            add_edge(p,p+1,f);
            add_edge(p+1,p,f);
        }
    }
    for(int i=1,p,f;i<n;++i)
    {
        for(int j=1;j<=m;++j)
        {
            p=(i-1)*m+j;
            f=read(),
            add_edge(p,p+m,f);
            add_edge(p+m,p,f);
        }
    }
    for(int i=1,p,f;i<n;++i)
    {
        for(int j=1;j<m;++j)
        {
            p=(i-1)*m+j;
            f=read();
            add_edge(p,p+m+1,f);
            add_edge(p+m+1,p,f);
        }
    }
    long long ans=0;
    while(bfs())
        ans+=1ll*dfs(S,0x7fffffff);
    printf("%lld",ans);
    return 0;
}

 

posted @ 2018-09-12 11:12  whymhe  阅读(219)  评论(0编辑  收藏  举报