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

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

传送门:圈地 ( ext{[JSOI2015] [P6094]}) ( ext{[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
",ans-T1.maxflow);
}
原文地址:https://www.cnblogs.com/Xing-Ling/p/12713249.html