题面:
思路:
相邻的点不能同时取,那么在这个图中,实际上分了两种格子,每种格子相互之间随便取
那么就是二分图了
把相邻的点之间连边,得到一个二分图,我们实际上就是要求这个图的带权最大独立集
于是这道题转化为二分图问题,而二分图中最大独立集等于全集减去最小点覆盖,最小点覆盖等于这个图的最大匹配(都带权)
那么用网络流做就好了
将这个平面上的方格像国际象棋那样黑白染色
源点连黑点,容量为黑点权值
黑点连白点,容量为inf
白点连汇点,容量为白点权值
跑S-T最大流(即S-T最小割),用所有点的权值和减去最大流值,就得到了答案
因为在这个建好的网络流图里面,最大流等于最小割等于最小点覆盖
Code:
建图比较丑,请见谅
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define inf 0x7fffffff 6 using namespace std; 7 inline int read(){ 8 int re=0,flag=1;char ch=getchar(); 9 while(ch>'9'||ch<'0'){ 10 if(ch=='-') flag=-1; 11 ch=getchar(); 12 } 13 while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar(); 14 return re*flag; 15 } 16 inline int _min(int l,int r){return (l>r)?r:l;} 17 const int dx[5]={0,-1,0,1,0},dy[5]={0,0,-1,0,1}; 18 int n,m,cnt=-1,ans,x[50][50],first[2500],dep[2500],cur[2500]; 19 struct edge{ 20 int to,next,w; 21 }a[500010]; 22 inline void add(int u,int v,int w){ 23 // cout<<"add "<<u<<ends<<v<<ends<<w<<endl; 24 a[++cnt].to=v;a[cnt].next=first[u];first[u]=cnt;a[cnt].w=w; 25 a[++cnt].to=u;a[cnt].next=first[v];first[v]=cnt;a[cnt].w=0; 26 } 27 inline bool bfs(int s,int t){ 28 int q[2500],head=0,tail=1,i,u,v; 29 for(i=s;i<=t;i++) dep[i]=inf,cur[i]=first[i]; 30 q[0]=s;dep[s]=0; 31 while(head<tail){ 32 u=q[head++]; 33 // cout<<"bfs "<<u<<ends<<dep[u]<<ends<<head<<ends<<tail<<endl; 34 for(i=first[u];~i;i=a[i].next){ 35 v=a[i].to; 36 if(!a[i].w||dep[v]!=inf) continue; 37 // cout<<"to "<<v<<endl; 38 dep[v]=dep[u]+1; 39 q[tail++]=v; 40 } 41 // system("pause"); 42 } 43 return dep[t]!=inf; 44 } 45 int dfs(int u,int t,int low){ 46 // cout<<"dfs "<<u<<ends<<t<<ends<<low<<endl; 47 if(u==t||!low) return low; 48 int flow=0,f,i,v; 49 for(i=cur[u];~i;i=a[i].next){ 50 cur[u]=i;v=a[i].to; 51 if(dep[v]==dep[u]+1&&(f=dfs(v,t,_min(low,a[i].w)))){ 52 // cout<<"in "<<u<<" return from "<<v<<ends<<f<<endl; 53 flow+=f;low-=f; 54 a[i].w-=f;a[i^1].w+=f; 55 if(!low) break; 56 } 57 } 58 // cout<<"return "<<u<<ends<<t<<ends<<low<<ends<<flow<<endl; 59 return flow; 60 } 61 void dinic(){ 62 while(bfs(0,n*m+1)) ans+=dfs(0,n*m+1,inf); 63 } 64 int main(){ 65 freopen("grid.in","r",stdin); 66 freopen("grid.out","w",stdout); 67 memset(first,-1,sizeof(first)); 68 int i,j,k,ti,tj; 69 n=read();m=read(); 70 for(i=1;i<=n;i++) for(j=1;j<=m;j++) x[i][j]=read(),ans-=x[i][j]; 71 for(i=1;i<=n;i++){ 72 for(j=1;j<=m;j++){ 73 if((i+j)&1) add((i-1)*m+j,n*m+1,x[i][j]); 74 else add(0,(i-1)*m+j,x[i][j]); 75 if((i+j)&1) continue; 76 for(k=1;k<=4;k++){ 77 ti=i+dx[k];tj=j+dy[k]; 78 if(ti<1||ti>n||tj<1||tj>m) continue; 79 add((i-1)*m+j,(ti-1)*m+tj,inf); 80 } 81 } 82 } 83 dinic(); 84 printf("%d",-ans); 85 }