Link:
Solution:
方格取数和最大且要求两两没有公共边
遇到方格内的不相邻问题,考虑黑白染色来对点分类
问题转化为使黑点不和白点相邻的最小代价,其中每个点的代价只计算一次
明显的集合划分模型,用最小割解决:
$<S,black,w>,<white,T,w>,<blakc,white,INF>$
Code:
#include <bits/stdc++.h> using namespace std; #define X first #define Y second typedef long long ll; typedef pair<int,int> P; const int MAXN=1e5+10,INF=1<<30; int n,m,dat[105][105],sum; namespace Maxflow { struct edge{int nxt,to,cap;}e[MAXN<<2]; int S,T,head[MAXN],iter[MAXN],dist[MAXN],tot=-1; void add_edge(int from,int to,int cap) { e[++tot].nxt=head[from];e[tot].to=to;e[tot].cap=cap;head[from]=tot; e[++tot].nxt=head[to];e[tot].to=from;e[tot].cap=0;head[to]=tot; } bool bfs() { memset(dist,-1,sizeof(dist)); queue<int> q;q.push(S);dist[S]=0; while(!q.empty()) { int v=q.front();q.pop(); for(int i=head[v];i!=-1;i=e[i].nxt) { if(e[i].cap&&dist[e[i].to]==-1) dist[e[i].to]=dist[v]+1,q.push(e[i].to); } } return dist[T]!=-1; } int dfs(int v,int f) { if(v==T) return f; int ret=0; for(int &i=iter[v];i!=-1;i=e[i].nxt) if(dist[e[i].to]==dist[v]+1&&e[i].cap) { int d=dfs(e[i].to,min(f,e[i].cap)); e[i].cap-=d;e[i^1].cap+=d; f-=d;ret+=d;if(!f) break; } return ret; } int Dinic() { int ret=0; while(bfs()) { for(int i=0;i<MAXN;i++) iter[i]=head[i]; ret+=dfs(S,INF); } return ret; } } using namespace Maxflow; int dx[]={0,0,1,-1},dy[]={1,-1,0,0}; int idx(int x,int y){return (x-1)*m+y;} int main() { scanf("%d%d",&n,&m); S=0;T=n*m+1; memset(head,-1,sizeof(head)); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&dat[i][j]),sum+=dat[i][j]; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if((i+j)%2==1) add_edge(idx(i,j),T,dat[i][j]); else { add_edge(S,idx(i,j),dat[i][j]); for(int k=0;k<4;k++) { int fx=i+dx[k],fy=j+dy[k]; if(fx<1||fx>n||fy<1||fy>m) continue; add_edge(idx(i,j),idx(fx,fy),INF); } } printf("%d",sum-Dinic()); return 0; }