黑白染色,黑点s-(i,j)连a(i,j)的边,白色(i,j)-t连b(i,j)的边。
有关系的两点间连两点c之和的双向边。
最小割。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
queue<int> q;
int read()
{
char ch=getchar();int f=0,x=1;
while(ch<'0'||ch>'9'){if(ch=='-') x=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){f=(f<<1)+(f<<3)+ch-'0';ch=getchar();}
return f*x;
}
int n,m,a[105][105],b[105][105],c[105][105],s,t,sum;
int movex[5]={0,0,0,1,-1};
int movey[5]={0,1,-1,0,0};
int trans(int x,int y)
{
return (x-1)*(m)+y;
}
struct node
{
int from;
int to;
int next;
int w;
}edge[500005];
int tot,head[100005],dis[10005],ans;
void add(int u,int v,int w)
{
edge[tot].from=u;
edge[tot].to=v;
edge[tot].w=w;
edge[tot].next=head[u];
head[u]=tot++;
}
bool bfs()
{
memset(dis,-1,sizeof(dis));
dis[s]=0;
q.push(s);
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=head[x];i!=-1;i=edge[i].next)
{
if(dis[edge[i].to]==-1&&edge[i].w)
{
dis[edge[i].to]=dis[x]+1;
q.push(edge[i].to);
}
}
}
if(dis[t]==-1) return 0;
return 1;
}
int dfs(int x,int flow)
{//cout<<"ok";
if(x==t||!flow) return flow;
int ret=0;
for(int i=head[x];i!=-1;i=edge[i].next)
{
if(dis[edge[i].to]==dis[x]+1)
{
int f=dfs(edge[i].to,min(flow,edge[i].w));
edge[i].w-=f;edge[i^1].w+=f;
ret+=f;flow-=f;
if(!flow) break;
}
}
if(!ret) dis[x]=-1;
return ret;
}
void dinic()
{
while(bfs())
{
ans+=dfs(s,0x7f7f7f7f);
}
}
int main()
{
memset(head,-1,sizeof(head));
n=read();m=read();s=0,t=n*m+1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
a[i][j]=read();
sum+=a[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
b[i][j]=read();
sum+=b[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if((i+j)&1)
{
add(s,(i-1)*m+j,a[i][j]);
add((i-1)*m+j,s,0);
add((i-1)*m+j,t,b[i][j]);
add(t,(i-1)*m+j,0);
}
else
{
add(s,(i-1)*m+j,b[i][j]);
add((i-1)*m+j,s,0);
add((i-1)*m+j,t,a[i][j]);
add(t,(i-1)*m+j,0);
}
c[i][j]=read();
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if((i+j)&1) continue;
for(int k=1;k<=4;k++)
{
if(i+movex[k]>=1&&i+movex[k]<=n&&j+movey[k]>=1&&j+movey[k]<=m)
{
add(trans(i,j),trans(i+movex[k],j+movey[k]),c[i][j]+c[movex[k]+i][j+movey[k]]);
add(trans(i+movex[k],j+movey[k]),trans(i,j),c[i][j]+c[movex[k]+i][j+movey[k]]);
sum+=c[i][j]+c[movex[k]+i][j+movey[k]];
}
}
}
}
//cout<<"ok";
//for(int i=0;i<tot;i++) cout<<edge[i].to<<" "<<edge[i].w<<endl;
dinic();
cout<<sum-ans;
}