【BZOJ】【2132】圈地计划

网络流/最小割



  Orz Hzwer

  这类大概是最小割建模中的经典应用吧……

  黑白染色,然后反转黑色的技巧感觉很巧妙!这个转化太神奇了……

  1 /**************************************************************
  2     Problem: 2132
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:0 ms
  7     Memory:6252 kb
  8 ****************************************************************/
  9
 10 //BZOJ 2132
 11 #include<vector>
 12 #include<cstdio>
 13 #include<cstring>
 14 #include<cstdlib>
 15 #include<iostream>
 16 #include<algorithm>
 17 #define rep(i,n) for(int i=0;i<n;++i)
 18 #define F(i,j,n) for(int i=j;i<=n;++i)
 19 #define D(i,j,n) for(int i=j;i>=n;--i)
 20 #define FOR for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
 21 #define pb push_back
 22 using namespace std;
 23 inline int getint(){
 24     int v=0,sign=1; char ch=getchar();
 25     while(ch<‘0‘||ch>‘9‘){ if (ch==‘-‘) sign=-1; ch=getchar();}
 26     while(ch>=‘0‘&&ch<=‘9‘){ v=v*10+ch-‘0‘; ch=getchar();}
 27     return v*sign;
 28 }
 29 const int N=10010,M=300000,INF=~0u>>2;
 30 const int fx[]={1,0,-1,0},
 31           fy[]={0,1,0,-1};
 32 typedef long long LL;
 33 /******************tamplate*********************/
 34 int n,m,a[101][101],b[101][101],c[101][101],color[101][101],tot,ans;
 35 struct edge{
 36     int from,to,v;
 37 };
 38 inline int pack(int i,int j){ return (i-1)*m+j; }
 39 struct Net{
 40     edge E[M];
 41     int head[N],next[M],cnt;
 42     bool vis[110][110];
 43     void ins(int x,int y,int v){
 44         E[++cnt]=(edge){x,y,v};
 45         next[cnt]=head[x]; head[x]=cnt;
 46     }
 47     void add(int x,int y,int v){
 48         ins(x,y,v); ins(y,x,0);
 49     }
 50     void add2(int x,int y,int v){
 51         ins(x,y,v); ins(y,x,v);
 52     }
 53     int s,t,d[N],Q[N];
 54     void init(){
 55         n=getint();m=getint();
 56         cnt=1;tot=ans=0;
 57         s=0;t=n*m+1;
 58         int x,y;
 59         memset(a,-1,sizeof a);
 60         FOR a[i][j]=getint();
 61         FOR b[i][j]=getint();
 62         FOR c[i][j]=getint();
 63         FOR if ((i+j)&1) color[i][j]=1;
 64         FOR{
 65             if (color[i][j]) swap(a[i][j],b[i][j]);
 66             tot+=a[i][j]+b[i][j];
 67             add(s,pack(i,j),a[i][j]);
 68             add(pack(i,j),t,b[i][j]);
 69             if (color[i][j]) rep(k,4){
 70                 int tx=i+fx[k],ty=j+fy[k];
 71                 if (!tx||!ty||tx>n||ty>m) continue;
 72                 add2(pack(i,j),pack(tx,ty),c[i][j]+c[tx][ty]);
 73                 tot+=c[i][j]+c[tx][ty];
 74             }
 75         }
 76     }
 77     bool mklevel(){
 78         memset(d,-1,sizeof d);
 79         d[s]=0;
 80         int l=0,r=-1;
 81         Q[++r]=s;
 82         while(l<=r){
 83             int x=Q[l++];
 84             for(int i=head[x];i;i=next[i])
 85                 if (d[E[i].to]==-1 && E[i].v){
 86                     d[E[i].to]=d[x]+1;
 87                     Q[++r]=E[i].to;
 88                 }
 89         }
 90         return d[t]!=-1;
 91     }
 92     int dfs(int x,int a){
 93         if(x==t)return a;
 94         int flow=0;
 95         for(int i=head[x];i && flow<a;i=next[i])
 96             if (d[E[i].to]==d[x]+1 && E[i].v){
 97                 int f=dfs(E[i].to,min(a-flow,E[i].v));
 98                 E[i].v-=f;
 99                 E[i^1].v+=f;
100                 flow+=f;
101             }
102         if (!flow) d[x]=-1;
103         return flow;
104     }
105     void Dinic(){
106         while(mklevel()) ans+=dfs(s,INF);
107     }
108 }G1;
109 int main(){
110 #ifndef ONLINE_JUDGE
111     freopen("2132.in","r",stdin);
112     freopen("2132.out","w",stdout);
113 #endif
114     G1.init(); G1.Dinic();
115     printf("%d\n",tot-ans);
116     return 0;
117 }

时间: 2025-01-19 22:24:54

【BZOJ】【2132】圈地计划的相关文章

BZOJ 2132 圈地计划(最小割)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2132 题意:n*m的格子染色黑白,对于格子(i,j)染黑色则价值为A[i][j],白色为B[i][j].若一个格子四周不同颜色的有x个,则额外的价值为x*C[i][j].求最大价值. 思路:将格子黑白染色分成两个集合X和Y.S集合为X中的A和Y中的B,T为X中的B和Y中的A.相邻的连边为两个格子的C值之和.总权值减去最小割即是答案. struct node { int v,cap,ne

bzoj 2132: 圈地计划

1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define M 100009 5 #define inf 2139062143 6 using namespace std; 7 int n,m,a[102][102],b[102][102],c[102][102],tot,cnt=1,T,ans,head[M],d[M],q[2*M],next[10*M],u[10*M],v[10*M];

BZOJ 2132 圈地计划 最小割

题目大意:给定一个m*n的矩阵,每个位置如果作为商业区或者工业区各有一个收益,如果相邻两块是不同的也会有一个收益,求最大收益 吐槽:住宅区呢- - 地理老师骗我们- - 普通的最小割建图会遇到一个问题: 割断两块之间的边收益为正,即代价为负 因此我们如果正常建最小割,那么两块之间的边权就会是负的 那么我们将这个矩阵黑白染色,将白格ST反向 这样割断两块之间的连边相当于两块选择了同一用途,代价为正 就可以正常跑了 #include <cstdio> #include <cstring>

bzoj2132圈地计划

bzoj2132圈地计划 题意: 一块土地可以纵横划分为N×M块小区域.于第i行第j列的区域,建造商业区将得到Aij收益,建造工业区将得到Bij收益.而如果区域(i,j)相邻(相邻是指两个格子有公共边)有K块(显然K不超过4)类型不同于(i,j)的区域,则这块区域能增加k×Cij收益.已知收益矩阵A,B,C,求收益最大值. 题解: 因为附加收益不是两两之间的,所以不用考虑除以2的问题.由于需要两块土地属性不同,所以对整个棋盘进行黑白染色.如果一块土地A为黑色,则s->A :c[A商] A->T

【BZOJ2132】圈地计划 最小割

[BZOJ2132]圈地计划 Description 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地.据了解,这块土地是一块矩形的区域,可以纵横划分为N×M块小区域.GDOI要求将这些区域分为商业区和工业区来开发.根据不同的地形环境,每块小区域建造商业区和工业区能取得不同的经济价值.更具体点,对于第i行第j列的区域,建造商业区将得到Aij收益,建造工业区将得到Bij收益.另外不同的区域连在一起可以得

BZOJ 3232: 圈地游戏 分数规划+判负环

3232: 圈地游戏 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 966  Solved: 466[Submit][Status][Discuss] Description DZY家的后院有一块地,由N行M列的方格组成,格子内种的菜有一定的价值,并且每一条单位长度的格线有一定的费用. DZY喜欢在地里散步.他总是从任意一个格点出发,沿着格线行走直到回到出发点,且在行走途中不允许与已走过的路线有任何相交或触碰(出发点除外).记这条封闭路线内部的格

BZOJ 786水题计划

已完成 1/300 BZOJ第7页: BZOJ1600 : DP

BZOJ 3707: 圈地 计算几何

Description 2维平面上有n个木桩,黄学长有一次圈地的机会并得到圈到的土地,为了体现他的高风亮节,他要使他圈到的土地面积尽量小.圈地需要圈一个至少3个点的多边形,多边形的顶点就是一个木桩,圈得的土地就是这个多边形内部的土地.(因为黄学长非常的神,所以他允许圈出的第n点共线,那样面积算0) Input 第一行一个整数n,表示木桩个数.接下来n行,每行2个整数表示一个木桩的坐标,坐标两两不同. 题解: 简单的说就是给定平面上n个点,求这n个点组成三角形的最小面积. 如果分别枚举三个点的话是

BZOJ 4326 NOIP2015 运输计划 (二分+树上差分)

题意:中文题. 析:首先二分是很容易想出来的,然后主要是判断这个解合不合法,先二分答案 mid,因为有 m 个计划,所以只要添加虫洞的肯定是所有的时间长于 mid 的计划 中,也就是是那些的共同边,这个就可以用树上差分来做了,假设 s 到 t,那么让in[s]++,in[t]++,in[lca(s, t)] -= 2,其中in 表示的是 该结点与其父结点的边的计数,最后再跑一次dfs,把所有的权值都累加上去,这样就能知道哪些是共同的边了. 代码如下: #pragma comment(linker