考虑最小割 然后列方程 建图
大概就是hzwer 说的那样:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define LL long long
using namespace std;
#define F(x,y) for(int i=1;i<=x;i++) for(int j=1;j<=y;j++)
//by zfy =.=
struct node{
int next,v,c,f;
}e[350001];
queue<int> q;
int num=1,first[10002],n,m,a[102][102],b[102][102],tot,id[102][102],d[10002],ans;
const int T=10001,S=0,inf=2000000000;
void add(int u,int v,int c){
e[++num].next=first[u];first[u]=num;
e[num].v=v;e[num].c=c;
}
void ins1(int u,int v,int c){
add(u,v,c);add(v,u,c);
}
void ins2(int u,int v,int c){
add(u,v,c);add(v,u,0);
}
void build(){int x;
F(n-1,m) {
scanf("%d",&x);a[i][j]+=x;a[i+1][j]+=x;
tot+=x;ins1(id[i][j],id[i+1][j],x);
}
F(n-1,m) {
scanf("%d",&x);b[i][j]+=x;b[i+1][j]+=x;
tot+=x;ins1(id[i][j],id[i+1][j],x);
}
F(n,m-1) {
scanf("%d",&x);a[i][j]+=x;a[i][j+1]+=x;
tot+=x;ins1(id[i][j],id[i][j+1],x);
}
F(n,m-1) {
scanf("%d",&x);b[i][j]+=x;b[i][j+1]+=x;
tot+=x;ins1(id[i][j],id[i][j+1],x);
}
F(n,m) {
ins2(0,id[i][j],a[i][j]);
ins2(id[i][j],T,b[i][j]);
}
}
int bfs(){
memset(d,0,sizeof d);d[S]=1;q.push(S);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=first[u];i;i=e[i].next){
int v=e[i].v;
if(!d[v]&&e[i].c>e[i].f){
d[v]=d[u]+1;q.push(v);
}
}
}return d[T];
}
int dfs(int x,int a){
if(x==T||a==0) return a;
int tmp,f=0;
for(int i=first[x];i;i=e[i].next){
int v=e[i].v;
if(d[v]==d[x]+1&&(tmp=dfs(v,min(a,e[i].c-e[i].f)))){
a-=tmp;f+=tmp;
e[i].f+=tmp;e[i^1].f-=tmp;
if(!a) break;
}
}if(!f) d[x]=0;
return f;
}
void dinic(){
while(bfs()) {ans+=dfs(0,inf);}
}
int main(){
scanf("%d%d",&n,&m);
F(n,m) {scanf("%d",&a[i][j]);tot+=a[i][j];a[i][j]<<=1;}
F(n,m) {scanf("%d",&b[i][j]);tot+=b[i][j];b[i][j]<<=1;}
F(n,m) id[i][j]=(i-1)*m+j;
build();dinic();
printf("%d",tot-(ans/2));
return 0;
}