这个系列终于做完了。。
又是一道网络流
因为不能取相邻的点,很容易发现需要二分图
一半的点连源,另一半连汇,流量为map[i,j]
相邻的点连起来,流量为inf
答案就是总和减最大流
最大流。。。看这篇吧
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 0x3f3f3f3f
#define g getchar
#define ll long long
#define maxe 10020
#define maxn 1010
using namespace std;
struct re{int v,next,fl;}ed[maxe];
int e,m,n,ans,sum;
int head[maxn],pd[maxn],dui[maxe];
inline void ins(int x,int y,int w){
ed[++e].v=y;ed[e].fl=w;ed[e].next=head[x];head[x]=e;
ed[++e].v=x;ed[e].fl=0;ed[e].next=head[y];head[y]=e;
}
void init(){
scanf("%d%d",&m,&n);
for(int i=1;i<=m;++i)
for(int j=1;j<=n;++j){
int x;
scanf("%d",&x);
if(!((i+j)%2)){
ins(0,(i-1)*n+j,x);
if(i>1)ins((i-1)*n+j,(i-2)*n+j,inf);
if(i<m)ins((i-1)*n+j,i*n+j,inf);
if(j>1)ins((i-1)*n+j,(i-1)*n+j-1,inf);
if(j<n)ins((i-1)*n+j,(i-1)*n+j+1,inf);
}
else ins((i-1)*n+j,n*m+1,x);
sum+=x;
}
}
bool bfs(){
memset(pd,-1,sizeof(pd));
int tou=1,wei=1;
dui[1]=0;
pd[0]=0;
for(;tou<=wei;++tou){
int u=dui[tou];
for(int i=head[u];i;i=ed[i].next){
if(ed[i].fl&&pd[ed[i].v]<0){
pd[ed[i].v]=pd[u]+1;
dui[++wei]=ed[i].v;
}
}
}
return pd[n*m+1]!=-1;
}
int dfs(int x,int w){
if(x==n*m+1)return w;
int used=0,le;
for(int i=head[x];i;i=ed[i].next){
if(ed[i].fl&&pd[ed[i].v]==pd[x]+1){
le=w-used;
le=dfs(ed[i].v,min(ed[i].fl,le));
used+=le;
ed[i].fl-=le;
ed[i%2?i+1:i-1].fl+=le;
if (used==w)return w;
}
}
if (!used)pd[x]=-1;
return used;
}
int main(){ //主程序还是一如既往的简洁
init();
while(bfs())
ans+=dfs(0,sum);
printf("%d",sum-ans);
return 0;
}