不要往费用流上想,要往最小割上想,舍弃的权值最小,然后就想一下放到哪边有哪些贡献,不同位置会割掉不同贡献的边,
然后枚举各种割的情况,赋边权就可以了
码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define N 10005
#define M 500005
int zhong[M],hou[M],W[105][105],L[105][105],TW[105][105],TL[105][105],yuan[N],xia[N],x,v[M],s,t,i,j,n,m,ans,tot=-1,cnt,d[N],tu[105][105];
queue<int>q;
void jian(int a,int b,int c)
{
++tot;zhong[tot]=b;hou[tot]=yuan[a],yuan[a]=tot,v[tot]=c;
}
void jia(int a,int b,int c)
{
jian(a,b,c);
jian(b,a,0);
}
bool bfs()
{
int i;
for(i=1;i<=cnt;i++)xia[i]=yuan[i],d[i]=999999999;
q.push(s);
d[s]=0;
while(!q.empty())
{
int st=q.front();
q.pop();
for(i=xia[st];i!=-1;i=hou[i])
{
if(v[i]==0)continue;
int nd=zhong[i];
if(d[nd]==999999999)
{
d[nd]=d[st]+1;
q.push(nd);
}
}
}
if(d[t]==999999999)return 0;
return 1;
}
int dfs(int o,int limit)
{
if(o==t||!limit)return limit;
int i,f,flow=0,nd;
for(i=xia[o];i!=-1;i=hou[i])
{
nd=zhong[i];
xia[o]=i;
if(d[nd]==d[o]+1&&(f=dfs(nd,min(limit,v[i]))))
{
v[i]-=f;
v[i^1]+=f;
flow+=f;
limit-=f;
if(!limit)break;
}
}
return flow;
}
int dinic()
{
int daan=0;
while(bfs())
{
daan+=dfs(s,999999999);
}
return daan;
}
int main()
{
memset(yuan,-1,sizeof(yuan));
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
tu[i][j]=++cnt;
scanf("%d",&x);W[i][j]+=x;
ans+=x;
}
s=++cnt;
t=++cnt;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
scanf("%d",&x);L[i][j]+=x;
ans+=x;
}
for(i=1;i<n;i++)
for(j=1;j<=m;j++)
{
scanf("%d",&x);
TW[i][j]+=x;ans+=x;
jia(tu[i+1][j],tu[i][j],x);
}
for(i=1;i<n;i++)
for(j=1;j<=m;j++)
{
scanf("%d",&x);
TL[i][j]+=x;ans+=x;
jia(tu[i][j],tu[i+1][j],x);
}
for(i=1;i<=n;i++)
for(j=1;j<m;j++)
{
scanf("%d",&x);
TW[i][j]+=x;ans+=x;
jia(tu[i][j+1],tu[i][j],x);
}
for(i=1;i<=n;i++)
for(j=1;j<m;j++)
{
scanf("%d",&x);
TL[i][j]+=x;ans+=x;
jia(tu[i][j],tu[i][j+1],x);
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
jia(s,tu[i][j],L[i][j]+TL[i][j]);//割掉损失选理
jia(tu[i][j],t,W[i][j]+TW[i][j]);//割掉损失选文
}
printf("%d",ans-dinic());
}