【题解】圈地 [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);
}