题目:dtoj1246方格取数问题,dtoj1261骑士共存问题
这些题目都是一个思路拉,如果把整个方盘间隔着黑白染色,同色之间不会互相影响,所以可以把两个颜色分别连在 $s$ 和 $t$ 上,中间相连的边表示两者的关系,常常是总的收益减去最小割的收益是答案要求的最大收益拉~
放个方格取数的代码吧!
#include<bits/stdc++.h> #define _(d) while(d(isdigit(ch=getchar()))) #define il inline using namespace std; const int N=3510,M=20010,inf=1e9;queue<int> q; int n,m,head[N],ne[M],to[M],v[M],d[N],ans,res,cnt=1,s,t; int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;return f*x;} il void insert(int x,int y,int z){ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;v[cnt]=z;} il void add(int u,int v,int w){insert(u,v,w);insert(v,u,0);} il bool pd(int x,int y){if(x>0&&x<=m&&y>0&&y<=n)return 1;return 0;} il void link(int x,int y){ if(pd(x+1,y))add(x*n+y,(x+1)*n+y,inf);if(pd(x,y+1))add(x*n+y,x*n+y+1,inf); if(pd(x-1,y))add(x*n+y,(x-1)*n+y,inf);if(pd(x,y-1))add(x*n+y,x*n+y-1,inf); } il bool bfs(){ memset(d,-1,sizeof(d));q.push(s);d[s]=1; while(!q.empty()){ int x=q.front();q.pop(); for(int i=head[x];i;i=ne[i]){ if(!v[i]||d[to[i]]!=-1)continue; q.push(to[i]);d[to[i]]=d[x]+1; } } return d[t]!=-1; } int dfs(int x,int f){ if(x==t)return f;int w,used=0; for(int i=head[x];i;i=ne[i]){ if(d[x]+1!=d[to[i]]||(!v[i]))continue; w=f-used;w=dfs(to[i],min(w,v[i])); v[i]-=w;v[i^1]+=w;used+=w;if(used==f)return used; } if(!used)d[x]=-1;return used; } il void dinic(){while(bfs()){res+=dfs(s,inf);}} int main() { m=read();n=read();t=n*m+n+m+1;for(int i=1;i<=m;i++)for(int j=1;j<=n;j++){ int w=read();if((i+j)&1)add(i*n+j,t,w);else add(s,i*n+j,w),link(i,j);ans+=w; } dinic();ans-=res;printf("%d ",ans); return 0; }