传送门
按题意建个图跑最大流-最小割算法
以上纯属扯淡。
按如下方式建图(借用黄学长的blog):
s->A:cost[A文]+c[文][A][B]/2,s->B:cost[B文]+c[文][A][B]/2;
A->t:cost[A理]+c[理][A][B]/2,B->t:costB[理]+c[理][A][B]/2;
A<–>B:c[文][A][B]/2+c[理][A][B]/2
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1,inf=0x3f3f3f3f;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
const int M=10005,N=105;
int n,m,a[N][N],b[N][N],id[N][N],da[N][N],db[N][N],dc[N][N],dd[N][N];
struct edge{int v,next,c;};
namespace Dinic{
int d[M],first[M],cnt,s,t;
edge e[M*105];
inline void addedge(int u,int v,int c){e[++cnt]=(edge){v,first[u],c},first[u]=cnt;}
inline void add(int u,int v,int c){addedge(u,v,c),addedge(v,u,0);}
inline void Add(int u,int v,int c){addedge(u,v,c),addedge(v,u,c);}
inline void clear(){cnt=-1,memset(first,-1,sizeof(first)),s=0,t=n*m+1;}
inline bool bfs(){
queue<int>q;
for(ri i=s;i<=t;++i)d[i]=-1;
q.push(s),d[s]=0;
while(q.size()){
int x=q.front();
q.pop();
for(ri v,i=first[x];~i;i=e[i].next){
if(~d[v=e[i].v]||!e[i].c)continue;
d[v]=d[x]+1;
q.push(v);
}
}
return ~d[t];
}
inline int dfs(int x,int f){
if(!f||x==t)return f;
int flow=f;
for(ri i=first[x],tmp,v;~i;i=e[i].next){
if(!flow)return f;
if(d[v=e[i].v]!=d[x]+1||!e[i].c)continue;
tmp=dfs(v,min(flow,e[i].c));
if(!tmp)d[v]=-1;
e[i].c-=tmp,e[i^1].c+=tmp,flow-=tmp;
}
return f-flow;
}
inline int solve(){
int ret=0;
while(bfs())ret+=dfs(s,inf);
return ret;
}
}
int main(){
int ans=0;
n=read(),m=read();
Dinic::clear();
for(ri i=1,tim=0;i<=n;++i)for(ri j=1;j<=m;++j)id[i][j]=++tim;
for(ri i=1;i<=n;++i)for(ri j=1;j<=m;++j)ans+=(a[i][j]=read()),a[i][j]<<=1;
for(ri i=1;i<=n;++i)for(ri j=1;j<=m;++j)ans+=(b[i][j]=read()),b[i][j]<<=1;
for(ri i=1,v;i<n;++i)for(ri j=1;j<=m;++j)ans+=(v=read()),a[i][j]+=v,a[i+1][j]+=v,da[i][j]=v;
for(ri i=1,v;i<n;++i)for(ri j=1;j<=m;++j)ans+=(v=read()),b[i][j]+=v,b[i+1][j]+=v,db[i][j]=v;
for(ri i=1,v;i<=n;++i)for(ri j=1;j<m;++j)ans+=(v=read()),a[i][j]+=v,a[i][j+1]+=v,dc[i][j]=v;
for(ri i=1,v;i<=n;++i)for(ri j=1;j<m;++j)ans+=(v=read()),b[i][j]+=v,b[i][j+1]+=v,dd[i][j]=v;
for(ri i=1;i<=n;++i)for(ri j=1;j<=m;++j){
Dinic::add(Dinic::s,id[i][j],a[i][j]);
Dinic::add(id[i][j],Dinic::t,b[i][j]);
if(i^n)Dinic::Add(id[i][j],id[i+1][j],da[i][j]+db[i][j]);
if(j^m)Dinic::Add(id[i][j],id[i][j+1],dc[i][j]+dd[i][j]);
}
cout<<ans-Dinic::solve()/2;
return 0;
}