圈地计划

Description

最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地。据了解,这块土地是一块矩形的区域,可以纵横划分为N×M块小区域。GDOI要求将这些区域分为商业区和工业区来开发。根据不同的地形环境,每块小区域建造商业区和工业区能取得不同的经济价值。更具体点,对于第i行第j列的区域,建造商业区将得到Aij收益,建造工业区将得到Bij收益。另外不同的区域连在一起可以得到额外的收益,即如果区域(I,j)相邻(相邻是指两个格子有公共边)有K块(显然K不超过4)类型不同于(I,j)的区域,则这块区域能增加k×Cij收益。经过Tiger.S教授的勘察,收益矩阵A,B,C都已经知道了。你能帮GDOI求出一个收益最大的方案么?

Input

输入第一行为两个整数,分别为正整数N和M,分别表示区域的行数和列数;第2到N+1列,每行M个整数,表示商业区收益矩阵A;第N+2到2N+1列,每行M个整数,表示工业区收益矩阵B;第2N+2到3N+1行,每行M个整数,表示相邻额外收益矩阵C。第一行,两个整数,分别是n和m(1≤n,m≤100);

Output

输出只有一行,包含一个整数,为最大收益值。

Sample Input

3 3
1 2 3
4 5 6
7 8 9
9 8 7
6 5 4
3 2 1
1 1 1
1 3 1
1 1 1

Sample Output

81

【数据规模】
对于100%的数据有N,M≤100

观察题目,基本与happiness相同,所以基本也就是二分图的最小割,唯一有差别的是happiness中是属于相同的得到喜悦值,而这个是属于不同集合得到喜悦值。

这一点很难,这一点很难。

最先我想的是把中间的权令为-(w1+w2),但很明显网络流跑不起负的(可见我网络流多差,这个都不知道),然后怎么办呢?很难办。

既然我们不能用负边连体现这个关系。考虑happiness,A与B点同属于一个集合就得到这个喜悦值,注意到这里指的是属于S集,T集,那么一个精妙的变换方案出现了,我们先黑白染色,对于每个黑点A,S->A:W商业,A->T:W工业,

对于每个白点B,S->B:W工业,B->T:W商业,对于每对有关系的两点A,B,A<-->B:w1+w2。

一切问题就迎刃而解了,真是一种精妙的办法啊。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <ctime>
#include <cmath>
using namespace std;
int s,t;
int n,m;
int sum=0;
int C[200][200];
int tot=1;
int fir[200000],en[200000],nex[200000],f[200000];
void ins(int a,int b,int c,int d){
nex[++tot]=fir[a];
fir[a]=tot;
en[tot]=b;
f[tot]=c; nex[++tot]=fir[b];
fir[b]=tot;
en[tot]=a;
f[tot]=d;
}
int flow;
int d[200000],now[200000],num[200000],pre[200000],his[200000];
void sap(){
flow=0;
for (int i=0;i<=t;i++){
now[i]=fir[i];
d[i]=num[i]=0;
}
num[0]=t;
int aug=0x7fffffff;
bool flag;
int i=s;
while (d[s]<t){
his[i]=aug;
flag=false;
for (int k=now[i];k;k=nex[k])
if (f[k]>0&&d[i]==d[en[k]]+1){
aug=min(aug,f[k]);
flag=true;
now[i]=k;
pre[en[k]]=i;
i=en[k];
if (i==t){
flow+=aug;
while (i!=s){
i=pre[i];
f[now[i]]-=aug;
f[now[i]^1]+=aug;
}
aug=0x7fffffff;
}
break;
}
if (flag) continue;
int k1=0,minn=t;
for (int k=fir[i];k;k=nex[k])
if (f[k]>0&&minn>d[en[k]]){
k1=k;
minn=d[en[k]];
}
now[i]=k1;
if (!--num[d[i]]) return;
d[i]=minn+1;
num[d[i]]++; if (i!=s){
i=pre[i];
aug=his[i];
}
}
}
int main(){
// freopen("2132.in","r",stdin);
// freopen("2132.out","w",stdout);
scanf("%d%d",&n,&m);
s=n*m+1;t=n*m+2;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++){
int delta;
scanf("%d",&delta);
if ((i+j)%2==0) ins(s,(i-1)*m+j,delta,0);
if ((i+j)%2==1) ins((i-1)*m+j,t,delta,0);
sum+=delta;
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++){
int delta;
scanf("%d",&delta);
if ((i+j)%2==1) ins(s,(i-1)*m+j,delta,0);
if ((i+j)%2==0) ins((i-1)*m+j,t,delta,0);
sum+=delta;
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++){
scanf("%d",&C[i][j]);
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m-1;j++){
ins((i-1)*m+j,(i-1)*m+j+1,C[i][j]+C[i][j+1],C[i][j]+C[i][j+1]);
sum+=C[i][j]+C[i][j+1];
}
for (int i=1;i<=n-1;i++)
for (int j=1;j<=m;j++){
ins((i-1)*m+j,i*m+j,C[i][j]+C[i+1][j],C[i][j]+C[i+1][j]);
sum+=C[i][j]+C[i+1][j];
}
sap(); printf("%d",sum-flow); return 0;
}

[BZOJ]2132: 圈地计划 最小割的更多相关文章

  1. BZOJ 2131 圈地计划(最小割+黑白染色)

    类似于happiness的一道题,容易想到最小割的做法. 但是不同的是那一道题是相邻的如果相同则有收益,这题是相邻的不同才有收益. 转化到建图上面时,会发现,两个相邻的点连的边容量会是负数.. 有一种 ...

  2. BZOJ 2132 圈地计划(最小割)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2132 题意:n*m的格子染色黑白,对于格子(i,j)染黑色则价值为A[i][j],白色为 ...

  3. 【BZOJ2132】圈地计划 最小割

    [BZOJ2132]圈地计划 Description 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地. ...

  4. bzoj 2132 圈地计划(黑白染色,最小割)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2132 [题意] 给定n*m个区域,建工业区价值A,建商业区价值B,如果(i,j)有k个 ...

  5. bzoj 2132 圈地计划【最小割+dinic】

    对于网格图,尤其是这种要求相邻各自不同的,考虑黑白染色 对于这张染色后图来说: 对于每个黑格: 表示初始时选择商业区: s点向它连商业区收益的流量,它向t点连工业区收益的流量: 割断S侧的边说明反悔, ...

  6. bzoj 2132: 圈地计划

    #include<cstdio> #include<iostream> #include<cstring> #define M 100009 #define inf ...

  7. [BZOJ 3144] [Hnoi2013] 切糕 【最小割】

    题目链接:BZOJ - 3144 题目分析 题意:在 P * Q 的方格上填数字,可以填 [1, R] . 在 (x, y) 上填 z 会有 V[x][y][z] 的代价.限制:相邻两个格子填的数字的 ...

  8. [BZOJ 3894] 文理分科 【最小割】

    题目链接:BZOJ - 3894 题目分析 最小割模型,设定一个点与 S 相连表示选文,与 T 相连表示选理. 那么首先要加上所有可能获得的权值,然后减去最小割,即不能获得的权值. 那么对于每个点,从 ...

  9. BZOJ 2039 人员雇佣 二元关系 最小割

    题面太长了,请各位自行品尝—>人员雇佣 分析: 借用题解的描述: a.选择每个人有一个代价Ai b.如果有两个人同时选择就可以获得收益Ei,j c.如果一个人选择另一个不选会产生代价Ei,j 这 ...

随机推荐

  1. Move to Another Changelist

    Move to Another Changelist 将选中的文件转移到其他的 Change list 中. Change list 是一个重要的概念,这里需要进行重点说明.很多时候,我们开发一个项目 ...

  2. 1126. Magnetic Storms(单调队列)

    1126 最简单的单调队列应用吧 单调队列是指在一个队列中各个元素单调 递增(或者递减),并且各个元素的下标单调 递增. 单调队列的大体操作 进队时,将进队的元素为e,从队尾往前扫描,直到找到一个不大 ...

  3. bzoj3996

    把这个式子弄清楚就知道这是最小割了 相当于,选某个点i有收入ai,i,会损失ci, 如果i,j都被选则有额外收入ai,j+aj,i 明显,对每个点i,连(s,i,∑ai,j) (i,t,ci) 对每对 ...

  4. BZOJ3280: 小R的烦恼

    题解: 随便建一下图费用流就可以过吧... 代码: #include<cstdio> #include<cstdlib> #include<cmath> #incl ...

  5. Java [Leetcode 283]Move Zeroes

    题目描述: Given an array nums, write a function to move all 0's to the end of it while maintaining the r ...

  6. C++基类和派生类之间的转换

    本文讲解内容的前提是派生类继承基类的方式是公有继承,关键字public 以下程序为讲解用例. #include<iostream> using namespace std; class A ...

  7. js 中&& 与 ||

    /*** 几乎所有语言中||和&&都遵循“短路”原理,* 如&&中第一个表达式为假就不会去处理第二个表达式,而||正好相反.* js也遵循上述原则.* 当||时,找到为 ...

  8. 4.2 CUDA Reduction 一步一步优化

    Reduction并行分析: 每个线程是基于一个树状的访问模型,从上至下,上一层读取数据相加得到下一层的数据.不停的迭代,直到访问完所有的数据. 利用这么多的线程块(thread block)我们需要 ...

  9. 【原创】lua的module的一些点

    lua的module好像是5.1开始有的 在xx.lua的开头写上 module('my_module') 这行等价于如下几行 local name = 'my_module' local M = { ...

  10. 题解西电OJ (Problem 1005 -跳舞毯)--动态规划

    Description zyf不小心得了一种怪病,为了维持一天的精力他必须不停跳动.于是他买了一条跳舞毯,每天跳上几小时.众所周知,跳舞毯是给定一个序列,让你在指定时间踏指定的按钮,但zyf似乎不怎么 ...