【题解】:最大点权独立集
黑白染色,S到X集合中的点边容量为该点权值,Y到T同,不能同时取的两个格子连一条无穷大的边,结果是所有格子权值和减去最小割
//同题:【tyvj1338】QQ农场
#include<cstdio> #include<iostream> using namespace std; const int N=210,M=1e5+10; const int inf=0x3f3f3f3f; const int dx[]={0,0,1,-1}; const int dy[]={1,-1,0,0}; struct node{ int v,next,cap; }e[M*10];int tot=1; int n,m,num,S,T,id[N][N],mp[N][N],head[M],dis[M],q[M*10]; void add(int x,int y,int z){ e[++tot].v=y;e[tot].cap=z;e[tot].next=head[x];head[x]=tot; e[++tot].v=x;e[tot].cap=0;e[tot].next=head[y];head[y]=tot; } bool inside(int x,int y){ return x>0&&x<=n&&y>0&&y<=m; } bool bfs(){ for(int i=S;i<=T;i++) dis[i]=inf; int h=0,t=1;q[t]=S;dis[S]=0; while(h!=t){ int x=q[++h]; for(int i=head[x];i;i=e[i].next){ int v=e[i].v; if(e[i].cap&&dis[v]>dis[x]+1){ dis[v]=dis[x]+1; if(v==T) return 1; q[++t]=v; } } } return dis[T]<inf; } int dfs(int x,int f){ if(x==T) return f; int used=0,t; for(int i=head[x];i;i=e[i].next){ int v=e[i].v; if(e[i].cap&&dis[v]==dis[x]+1){ t=dfs(v,min(f,e[i].cap)); e[i].cap-=t;e[i^1].cap+=t; used+=t;f-=t; if(!f) return used; } } dis[x]=0; return used; } int dinic(){ int res=0; while(bfs()) res+=dfs(S,inf); return num-res; } void mapping(){ int cnt=0; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ id[i][j]=++cnt; } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if((i+j)&1^1){ add(S,id[i][j],mp[i][j]); for(int k=0;k<4;k++){ int nx=i+dx[k],ny=j+dy[k]; if(inside(nx,ny)) add(id[i][j],id[nx][ny],inf); } } else add(id[i][j],T,mp[i][j]); } } } int main(){ scanf("%d%d",&n,&m);S=0;T=n*m+1; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&mp[i][j]);num+=mp[i][j]; } } mapping(); printf("%d",dinic()); return 0; }