版权声明:虽然博主很菜,但是还是请注明出处(我觉得应该没人偷我的博客) https://blog.csdn.net/qq_43346903/article/details/88695401
这题可以发现我们把格子染色,使得相邻的格子的颜色不同,然后把白色格子和s连一条边,黑色格子和t连一条边,就转化为了最小割问题
Code:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=1000005,M=1000005;
const int inf=0x3f3f3f3f;
int a[105][105];
namespace Dinic{
int vis[M<<1],head[M<<1],nxt[M<<1],e[M<<1],tot=1;
inline void add(int x,int y,int z){
vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;e[tot]=z;
vis[++tot]=x;nxt[tot]=head[y];head[y]=tot;e[tot]=0;
}
int s,t,d[N];
queue<int>q;
inline bool spfa(){
memset(d,0,sizeof(d));
while(!q.empty()) q.pop();
q.push(s);d[s]=1;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=head[x];i;i=nxt[i]){
int y=vis[i];
if(!d[y] && e[i]){
q.push(y);
d[y]=d[x]+1;
if(y==t) return 1;
}
}
}
return 0;
}
int dinic(int x,int flow){
if(x==t) return flow;
int rest=flow,k;
for(int i=head[x];i && rest;i=nxt[i])
if(e[i] && d[vis[i]]==d[x]+1){
k=dinic(vis[i],min(e[i],rest));
if(!k) d[vis[i]]=0;
e[i]-=k;e[i^1]+=k;
rest-=k;
}
return flow-rest;
}
inline int maxflow(){
int flow=0,maxflow=0;
while(spfa())
while(flow=dinic(s,inf)) maxflow+=flow;
return maxflow;
}
}
using namespace Dinic;
int n,m;
int main(){
n=read();m=read();s=0,t=n*m+1;int cnt=0,sum=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
++cnt;
a[i][j]=read();sum+=a[i][j];
if((i+j)%2){
add(s,cnt,a[i][j]);
if(j<m) add(cnt,cnt+1,inf);
if(j>1) add(cnt,cnt-1,inf);
if(i<n) add(cnt,cnt+m,inf);
if(i>1) add(cnt,cnt-m,inf);
}
else add(cnt,t,a[i][j]);
}
cout<<sum-maxflow();
return 0;
}