題意:給定一個網格,每個網格有選取代價和佔據收益。每個點被佔據,需要滿足以下兩個條件至少一個條件:1.被選取  2.鄰近方格都被選取(有公共邊被稱為鄰近)  不一定要佔據所有方格,求最大收益。

第一直觀感受和文理分科那道題很像,這類肯定用最小割,這種題一般都這樣搞,但是建圖是個大問題。這道題建出來的圖要滿足,如果一個點要保留收益,那麼要麼自己的花費邊被割,要麼鄰近的被割,怎麼建呢?

考慮先黑白染色,拆點,然後我們S連向黑色,容量為花費,黑色向自己的分身連收益邊,並且黑色向相鄰的白色點的分身連INF,黑色分身向白色連INF,白色分身向自己連收益,白色向T連花費。

仔細觀察我們發現,確實能滿足要求。

這種題一般都是套路,我也不知道怎麼就要這麼建邊,不過可以總結出一些東西,比如一旦有關係,兩者之間都會連INF以確保能彼此影響又不會被最小割割中,然後花費和收益,拆點怎麼安排就要看具體的題目了。

上程式碼(與原題的輸入不一樣,是自己寫的)

#include<bits/stdc++.h>
using namespace std;
#define N 25
#define INF 1e9
#define id(x,y) ((x-1)*m+y)
inline int read(){
int x=,f=; char a=getchar();
while(a<'' || a>'') {if(a=='-') f=-; a=getchar();}
while(a>='' && a<='') x=x*+a-'',a=getchar();
return x*f;
}
const int dir[][]={,,-,,,,,-};
int n,m,be[N][N],co[N][N],S,T,P,ans,d[],head[],cur[],cnt;
bool vis[];
queue<int>q;
struct edges{
int to,cap,flow,next;
}e[];
inline void insert(int u,int v,int c){
e[cnt]=(edges){v,c,,head[u]};head[u]=cnt++;
e[cnt]=(edges){u,,,head[v]};head[v]=cnt++;
}
inline bool bfs(){
memset(vis,,sizeof(vis));
vis[S]=; d[S]=; q.push(S);
while(!q.empty()){
int x=q.front(); q.pop();
for(int i=head[x];i>=;i=e[i].next){
if(!vis[e[i].to] && e[i].cap>e[i].flow)
d[e[i].to]=d[x]+,q.push(e[i].to),vis[e[i].to]=;
}
}
return vis[T];
}
int dfs(int x,int a){
if(x==T || !a) return a;
int f,flow=;
for(int& i=cur[x];i>=;i=e[i].next){
if(d[e[i].to]==d[x]+ && (f=dfs(e[i].to,min(a,e[i].cap-e[i].flow)))>)
e[i].flow+=f,flow+=f,e[i^].flow-=f,a-=f;
if(!a) break;
}
return flow;
}
inline int maxflow(){
int flow=;
while(bfs()){
for(int i=S;i<=T;i++) cur[i]=head[i];
flow+=dfs(S,INF);
}
return flow;
}
int main(){
memset(head,-,sizeof(head));
n=read(); m=read();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
be[i][j]=read(),ans+=be[i][j];
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
co[i][j]=read();
S=; T=*n*m+; P=n*m;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++){
int x,y;
if((i+j)%){
insert(S,id(i,j),co[i][j]),insert(id(i,j),id(i,j)+P,be[i][j]);
for(int k=;k<;k++){
x=i+dir[k][],y=j+dir[k][];
if(x< || x>n || y< || y>m) continue;
insert(id(i,j),id(x,y)+P,INF);
insert(id(i,j)+P,id(x,y),INF);
}
}
else insert(id(i,j)+P,id(i,j),be[i][j]),insert(id(i,j),T,co[i][j]);
}
ans-=maxflow();
printf("%d\n",ans);
return ;
}