[bzoj2132]圈地计划
很显然是一个最小割的模型,将网格图黑白染色分为两类,黑的向S连工业费用,向T连商业费用,白的反过来即可
然后对于相邻的点,连上两个点的C之和(因为会产生两个),当然也可以变成两条边,就不需要存下C矩阵了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 10005 4 struct ji{ 5 int nex,to,len; 6 }edge[N*50]; 7 queue<int>q; 8 int E,n,m,x,ans,dx[4]={-1,0,0,1},dy[4]={0,-1,1,0},head[N],d[N],work[N]; 9 int id(int x,int y){ 10 return x*m+y+1; 11 } 12 void add(int x,int y,int z){ 13 edge[E].nex=head[x]; 14 edge[E].to=y; 15 edge[E].len=z; 16 head[x]=E++; 17 if (E&1)add(y,x,0); 18 } 19 bool bfs(){ 20 memset(d,-1,sizeof(d)); 21 q.push(0); 22 d[0]=0; 23 while (!q.empty()){ 24 int k=q.front(); 25 q.pop(); 26 for(int i=head[k];i!=-1;i=edge[i].nex) 27 if ((edge[i].len)&&(d[edge[i].to]<0)){ 28 d[edge[i].to]=d[k]+1; 29 q.push(edge[i].to); 30 } 31 } 32 return d[n*m+1]>=0; 33 } 34 int dfs(int k,int s){ 35 if (k>n*m)return s; 36 for(int &i=work[k];i!=-1;i=edge[i].nex) 37 if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){ 38 int p=dfs(edge[i].to,min(s,edge[i].len)); 39 if (p){ 40 edge[i].len-=p; 41 edge[i^1].len+=p; 42 return p; 43 } 44 } 45 return 0; 46 } 47 int dinic(){ 48 int k,ans=0; 49 while (bfs()){ 50 memcpy(work,head,sizeof(head)); 51 while (k=dfs(0,0x3f3f3f3f))ans+=k; 52 } 53 return ans; 54 } 55 int main(){ 56 scanf("%d%d",&n,&m); 57 memset(head,-1,sizeof(head)); 58 for(int i=0;i<n;i++) 59 for(int j=0;j<m;j++){ 60 scanf("%d",&x); 61 if ((i+j)&1)add(id(i,j),n*m+1,x); 62 else add(0,id(i,j),x); 63 ans+=x; 64 } 65 for(int i=0;i<n;i++) 66 for(int j=0;j<m;j++){ 67 scanf("%d",&x); 68 if ((i+j)&1)add(0,id(i,j),x); 69 else add(id(i,j),n*m+1,x); 70 ans+=x; 71 } 72 for(int i=0;i<n;i++) 73 for(int j=0;j<m;j++){ 74 scanf("%d",&x); 75 for(int k=0;k<4;k++){ 76 int tx=i+dx[k],ty=j+dy[k]; 77 if ((tx<0)||(ty<0)||(tx==n)||(ty==m))continue; 78 ans+=x; 79 add(id(i,j),id(tx,ty),x); 80 add(id(tx,ty),id(i,j),x); 81 } 82 } 83 printf("%d",ans-dinic()); 84 }