【题解】圈地 [JSOI2015] [P6094] [Bzoj4485]

【题解】圈地 [JSOI2015] [P6094] [Bzoj4485]

传送门:圈地 \(\text{[JSOI2015] [P6094]}\) \(\text{[Bzoj4485]}\)

【分析】

一道灰常简单的网络流。

设立超源和超汇,对于每个位置 \((i,j)\)

  • \(a>0\),超源向 \((i,j)\) 连一条容量为 \(a\) 的边

  • \(a<0\)\((i,j)\) 向超汇连一条容量为 \(-a\) 的边

对于每个墙,在被它隔离的两个位置之间分别向对方连一条容量为造墙价格的边。

最后答案为 \(\sum |a|\) 减去 最小割。

这题 \(Dinic\) 可以稳过,写 \(EK\) 会被卡到 \(70pts\)

【Code】

#include<algorithm>
#include<cstring>
#include<cstdio>
#define LL long long
#define Re register int
using namespace std;
const int N=160010,M=N*5,inf=2e9;
int n,m,x,st,ed,ans;
inline void in(Re &x){
    int f=0;x=0;char c=getchar();
    while(c<'0'||c>'9')f|=c=='-',c=getchar();
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    x=f?-x:x;
}
struct Dinic{
    int o,h,t,maxflow,Q[N],dis[N],cur[N],head[N];
    Dinic(){o=1;}
    struct QAQ{int to,next,flow;}a[M<<1];
    inline void add_(Re x,Re y,Re flow){a[++o].to=y,a[o].flow=flow,a[o].next=head[x],head[x]=o;}
    inline void add(Re x,Re y,Re flow){add_(x,y,flow),add_(y,x,0);}
    inline int bfs(Re st,Re ed){
        for(Re i=0;i<=ed;++i)dis[i]=0,cur[i]=head[i];
        h=1,t=0,Q[++t]=st,dis[st]=1;
        while(h<=t){
            Re x=Q[h++];
            for(Re i=head[x],to;i;i=a[i].next)
                if(a[i].flow&&!dis[to=a[i].to]){
                    dis[to]=dis[x]+1,Q[++t]=to;
                    if(to==ed)return 1;
                }
        }
        return 0;
    }
    inline int dfs(Re x,Re flow){
        if(x==ed||!flow)return flow;
        Re tmp=0,to,f;
        for(Re i=cur[x];i;i=a[i].next){
            cur[x]=i;
            if(dis[to=a[i].to]==dis[x]+1&&(f=dfs(to,min(flow-tmp,a[i].flow)))){
                a[i].flow-=f,a[i^1].flow+=f,tmp+=f;
                if(flow==tmp)break;
            }
        }
        return tmp;
    }
    inline void dinic(Re st,Re ed){while(bfs(st,ed))maxflow+=dfs(st,inf);}
}T1;
inline int Poi(Re i,Re j){return (i-1)*m+j;}
int main(){
//    freopen("123.txt","r",stdin);
    in(n),in(m),st=n*m+1,ed=st+1;
    for(Re i=1;i<=n;++i)
        for(Re j=1;j<=m;++j){
            in(x),ans+=(x>0?x:-x);
            if(x>0)T1.add(st,Poi(i,j),x);
            if(x<0)T1.add(Poi(i,j),ed,-x);
        }
    for(Re i=1;i<n;++i)
        for(Re j=1;j<=m;++j)
            in(x),T1.add(Poi(i,j),Poi(i+1,j),x),T1.add(Poi(i+1,j),Poi(i,j),x);
    for(Re i=1;i<=n;++i)
        for(Re j=1;j<m;++j)
            in(x),T1.add(Poi(i,j),Poi(i,j+1),x),T1.add(Poi(i,j+1),Poi(i,j),x);
    T1.dinic(st,ed),printf("%d\n",ans-T1.maxflow);
}
posted @ 2020-04-16 15:34  辰星凌  阅读(160)  评论(0编辑  收藏  举报