题目传送门
分析:
首先A和B2选1就是一组矛盾关系
然后相邻的两个格子选相同的也是一种矛盾
我们可以把格子染成黑白颜色,像国际象棋棋盘那样
对于黑格子,与S连容量为A的边,与T连容量为B的边
对于白格子,与S连容量为B的边,与T连容量为A的边
然后相邻格子,连容量为两个格子C之和的边
考虑正确性
同一个格子,A和B必须割一个
对于相邻格子,选相同和额外收益必须割一个
没有问题

#include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #define maxt 10005 #define maxn 105 #define INF 0x3f3f3f3f using namespace std; inline int getint() { int num=0,flag=1;char c; while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1; while(c>='0'&&c<='9')num=num*10+c-48,c=getchar(); return num*flag; } int n,m,S,T; int fir[maxt],nxt[20*maxt],to[20*maxt],cap[20*maxt],cnt; int a[maxn][maxn],b[maxn][maxn],c[maxn][maxn]; int col[maxn][maxn]; long long ans; int h[maxt]; inline int getid(int i,int j){return (i-1)*m+j;} inline void newnode(int u,int v,int w) {to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,cap[cnt]=w;} inline void insert(int u,int v,int w) {newnode(u,v,w),newnode(v,u,0);} inline bool bfs() { memset(h,-1,sizeof h); queue<int>Q;h[S]=0,Q.push(S); while(!Q.empty()) { int u=Q.front();Q.pop(); for(int i=fir[u];i;i=nxt[i]) if(cap[i]&&!~h[to[i]])h[to[i]]=h[u]+1,Q.push(to[i]); } return ~h[T]; } inline int dfs(int u,int flow) { if(u==T)return flow; int used=0; for(int i=fir[u];i;i=nxt[i]) if(cap[i]&&h[to[i]]==h[u]+1) { int w=flow-used; w=dfs(to[i],min(cap[i],w)); cap[i]-=w,cap[i^1]+=w,used+=w; if(used==flow)return flow; } if(!used)h[u]=-1; return used; } inline void dinic(){while(bfs())ans-=dfs(S,INF);} int main() { n=getint(),m=getint();S=n*m+1,T=S+1;cnt=1; for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)ans+=a[i][j]=getint(); for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)ans+=b[i][j]=getint(); for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)c[i][j]=getint(); for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)col[i][j]=(i+j)&1; for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) { if(col[i][j])swap(a[i][j],b[i][j]); insert(S,getid(i,j),a[i][j]),insert(getid(i,j),T,b[i][j]); if(i>1)ans+=c[i][j],insert(getid(i,j),getid(i-1,j),c[i][j]+c[i-1][j]); if(i<n)ans+=c[i][j],insert(getid(i,j),getid(i+1,j),c[i][j]+c[i+1][j]); if(j>1)ans+=c[i][j],insert(getid(i,j),getid(i,j-1),c[i][j]+c[i][j-1]); if(j<m)ans+=c[i][j],insert(getid(i,j),getid(i,j+1),c[i][j]+c[i][j+1]); } dinic(); printf("%lld ",ans); }
