BZOJ #3774. 最优选择
题面传送门
考试的时候硬干两个小时没肝出来。主要是或的地方没想出来。
我们考虑转化为最小割模型,并且将原图黑白染色。
对于白点,我们从源点向这个点连权值为\(A\)的边,表示如果这条边断掉,那么要付出A的代价将其选入。
对于黑点,令其连向汇点,同白点。
然后将每个点拆点,之间连权值为\(B\)的点。并且向四联通连权值为\(INF\)的点。
考虑这样建边的正确性。
如果一个点四周的A边都被割了,那么就不用付出代价。
对于两个点来说,只有两个B都割了才不会付出代价,符合题目,同时INF边不可能在割里面,所以只有上面两种情况、
然后跑看上去过不了的网络流就好了。
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N 5000
#define M 300000
#define mod 1000000007
#define Mod (mod-1)
#define eps (1e-5)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (m*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
using namespace std;
int n,m,A[N+5][N+5],B[N+5][N+5],x,y,d[N+5],nows[N+5],S,T,Ans,cnt;const int INF=1e9;
struct yyy{int to,w,z;}tmp;struct ljb{int head,h[N+5];yyy f[N+5<<4];I void add(int x,int y,int z){f[head]=(yyy){y,z,h[x]};h[x]=head++;}}s;
I void con(int x,int y,int z){s.add(x,y,z);s.add(y,x,0);/*printf("%d %d %d\n",x,y,z);*/}
int Xp[4]={0,1,0,-1};int Yp[4]={1,0,-1,0};queue<int> Q;
I int bfs(){
RI i;while(!Q.empty()) Q.pop();Q.push(S);Me(d,0x3f);d[S]=0;nows[S]=s.h[S];while(!Q.empty()){
for(x=Q.front(),Q.pop(),i=s.h[x];~i;i=tmp.z){
tmp=s.f[i];if(!tmp.w||d[tmp.to]<=1e9) continue;d[tmp.to]=d[x]+1;Q.push(tmp.to);nows[tmp.to]=s.h[tmp.to];if(tmp.to==T) return 1;
}
}return 0;
}
I int dfs(int x,int sum){
if(x==T) return sum;int i,pus=0,k;yyy tmp;for(i=nows[x];~i;i=tmp.z){
tmp=s.f[i];if(!tmp.w||d[tmp.to]!=d[x]+1) continue;nows[x]=i;k=dfs(tmp.to,min(sum,tmp.w));if(!k) d[tmp.to]=1e9;
s.f[i].w-=k;s.f[i^1].w+=k;pus+=k;sum-=k;if(!sum) break;
}return pus;
}
int main(){
freopen("1.in","r",stdin);
Me(s.h,-1);RI i,j,h;scanf("%d%d",&n,&m);S=0;T=2*n*m+1;for(i=1;i<=n;i++) for(j=1;j<=m;j++)scanf("%d",&A[i][j]);
for(i=1;i<=n;i++)for(j=1;j<=m;j++) scanf("%d",&B[i][j]),Ans+=B[i][j];
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if((i+j)&1) {con(S,d(i,j),A[i][j]);con(d(i,j),d(i,j)+n*m,B[i][j]);for(h=0;h<4;h++) x=i+Xp[h],y=j+Yp[h],x>=1&&x<=n&&y>=1&&y<=m&&(con(d(i,j),d(x,y)+n*m,INF),con(d(i,j)+n*m,d(x,y),INF),0);}
else con(d(i,j),T,A[i][j]),con(d(i,j)+n*m,d(i,j),B[i][j]);
}
} while(bfs()) Ans-=dfs(S,INF);printf("%d\n",Ans);
}