码迷,mamicode.com
首页 > 其他好文 > 详细

[bzoj2132]圈地计划

时间:2019-11-13 12:44:23      阅读:105      评论:0      收藏:0      [点我收藏+]

标签:一个   name   none   pop   return   scan   else   sizeof   tin   

很显然是一个最小割的模型,将网格图黑白染色分为两类,黑的向S连工业费用,向T连商业费用,白的反过来即可
然后对于相邻的点,连上两个点的C之和(因为会产生两个),当然也可以变成两条边,就不需要存下C矩阵了

技术图片
 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 }
View Code

 

[bzoj2132]圈地计划

标签:一个   name   none   pop   return   scan   else   sizeof   tin   

原文地址:https://www.cnblogs.com/PYWBKTDA/p/11847890.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!