2132: 圈地计划

题目:传送门

简要题意:

  给出一个矩阵,一共n*m个点,并给出三个收益矩阵。A矩阵表示这个点建A的可取收益,B矩阵表示这个点建B的可取收益,C矩阵表示如果相邻(有且仅有一条公共边)的点和自己所建的建筑不一样,则可获得C[i][j]的收益,如果相邻的有k个点和自己不一样,则收益为k*C[i][j]。求最大收益。

题解:

   日常一模最小割%%%ORZ

   本蒟蒻其实也看出是最小割什么的,但是怎么割啊。。。

   可能有人会和我有一样的疑惑:

   按照正常的割法建图:st到x连A收益,x到ed连B收益,两两之间再连C收益

   连完之后就蒙B了...割出来的是什么鬼???

   这时我们会发现,这样子连的话负权边根本没有体现啊???

  %题解啊啊啊:

   正解其实是需要进行黑白染色的(原因后面讲)

   染完色之后:st到黑点连A收益,黑点到ed连B收益;白点反之,然后相邻的不同颜色的格子相互连边(其实就是每个点还要连出去上下左右的点,因为染色了啊)

   这样之后用sum-最小割就OK。

   那染色是什么鬼:

   正确答案并不一定是相邻的点颜色都不一样,那么染色的目的就不是保证收益最大。

   但是染完色之后再跑最小割我们可以发现:

   如果某相邻两点异色的收益不如同色的收益,那么这条路径上关于相邻异色的收益肯定会被割掉

   如果异色收益更优,那割掉的肯定是一个A收益加一个B收益

   那么肯定是要最小割啊~

代码:

 #include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define qread(x) x=read()
using namespace std;
inline int read()
{
int f=,x=;char ch;
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return f*x;
}
struct node
{
int x,y,c,next,other;
}a[];int len,last[];
int n,m,st,ed,head,tail;
void ins(int x,int y,int c)
{
int k1,k2;
k1=++len;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=last[x];last[x]=len; k2=++len;
a[len].x=y;a[len].y=x;a[len].c=;
a[len].next=last[y];last[y]=len; a[k1].other=k2;
a[k2].other=k1;
}
int list[],h[];
bool bt_h()
{
memset(h,,sizeof(h));h[st]=;
list[]=st;head=;tail=;
while(head!=tail)
{
int x=list[head];
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(h[y]== && a[k].c>)
{
h[y]=h[x]+;
list[tail++]=y;
}
}
head++;
}
if(h[ed]>)return true;
return false;
}
int find_flow(int x,int flow)
{
if(x==ed)return flow;
int s=,t;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(h[y]==h[x]+ && a[k].c> && s<flow)
{
s+=t=find_flow(y,min(a[k].c,flow-s));
a[k].c-=t;a[a[k].other].c+=t;
}
}
if(s==)h[x]=;
return s;
}
int A[][],B[][],C[][];
int f[][];//黑白染色 1为黑 2为白
int d[][];
int main()
{
qread(n);qread(m);
len=;memset(last,,sizeof(last));
st=n*m+;ed=st+;
int s=;
for(int i=;i<=n;i++)for(int j=;j<=m;j++)d[i][j]=(i-)*m+j;
for(int i=;i<=n;i++)for(int j=;j<=m;j++)qread(A[i][j]);
for(int i=;i<=n;i++)for(int j=;j<=m;j++)qread(B[i][j]);
for(int i=;i<=n;i++)for(int j=;j<=m;j++)qread(C[i][j]);
memset(f,,sizeof(f));
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
if(i== && j==)continue;
if(j==)f[i][j]=f[i-][j]^;
else f[i][j]=f[i][j-]^;
}
int sum=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
sum+=A[i][j]+B[i][j];
if(f[i][j]==)
{
ins(st,d[i][j],A[i][j]);
ins(d[i][j],ed,B[i][j]);
}
else
{
ins(st,d[i][j],B[i][j]);
ins(d[i][j],ed,A[i][j]);
}
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
if(i->)ins(d[i][j],d[i-][j],C[i][j]+C[i-][j]),sum+=C[i][j];
if(i+<=n)ins(d[i][j],d[i+][j],C[i][j]+C[i+][j]),sum+=C[i][j];
if(j->)ins(d[i][j],d[i][j-],C[i][j]+C[i][j-]),sum+=C[i][j];
if(j+<=m)ins(d[i][j],d[i][j+],C[i][j]+C[i][j+]),sum+=C[i][j];
}
int ans=;
while(bt_h())ans+=find_flow(st,);
printf("%d\n",sum-ans);
return ;
}

bzoj2132: 圈地计划(无比强大的最小割)的更多相关文章

  1. bzoj2132圈地计划

    bzoj2132圈地计划 题意: 一块土地可以纵横划分为N×M块小区域.于第i行第j列的区域,建造商业区将得到Aij收益,建造工业区将得到Bij收益.而如果区域(i,j)相邻(相邻是指两个格子有公共边 ...

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

    题目 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地.据了解, 这块土地是一块矩形的区域,可以纵横划分 ...

  3. bzoj2132: 圈地计划

    要分成两坨对吧.. 所以显然最小割 但是不兹辞啊.. 最小割是最小的啊 求最大费用怎么玩啊 那咱们就把所有费用都加起来,减掉一个最小的呗 但是两个属于不同集合的点贡献的价值是负的啊 网络流怎么跑负的啊 ...

  4. bzoj 3232: 圈地游戏【分数规划+最小割】

    数组开小导致TTTTTLE-- 是分数规划,设sm为所有格子价值和,二分出mid之后,用最小割来判断,也就是判断sm-dinic()>=0 这个最小割比较像最大权闭合子图,建图是s像所有点连流量 ...

  5. bzoj 3232 圈地游戏 —— 01分数规划+最小割建图(最大权闭合子图)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3232 心烦意乱的时候调这道题真是...越调越气,就这样过了一晚上... 今天再认真看看,找出 ...

  6. bzoj2132: 圈地计划(最小割)

    传送门 看来以后见到矩形就要黑白染色冷静一下了…… 首先,如果它的要求时候相邻的选择相同,那么就是和这一题一样了->这里 然后考虑不同的要怎么做 那就把矩形黑白染色一下吧 然后令其中一种颜色的A ...

  7. 【BZOJ2132】圈地计划(最小割)

    [BZOJ2132]圈地计划(最小割) 题面 BZOJ 题解 对我而言,不可做!!! 所以我膜烂了ZSY大佬 他的博客写了怎么做... 这,,...太强啦!! 完全想不到黑白染色之后反着连边 然后强行 ...

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

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

  9. 【bzoj2132】圈地计划 网络流最小割

    题目描述 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地.据了解,这块土地是一块矩形的区域,可以纵横划 ...

随机推荐

  1. iOS CoreData 开发

    新年新气象,曾经的妹子结婚了,而光棍的我决定书写博客~ 废话结束. 本人不爱使用第三方的东东,喜欢原汁原味的官方版本,本次带来CoreData数据存储篇~ 创建应用

  2. Centos6.6 安装rsync服务端

    一.介绍 在工作中经常遇到代码分发,或者是资料备份,都会用到rsync,配置不算复杂,仅做下记录,安装环境如下: 1) Centos6.6 2) rsync-3.0.6-12.el6.x86_64 3 ...

  3. PHP 之simple_html_dom实现网页数据采集

    <?php set_time_limit(0); include './simple_html_dom.php'; $url = 'https://price.pcauto.com.cn/pri ...

  4. Echarts特效散点图全解

    mytextStyle={ color:"#333", //文字颜色 fontStyle:"normal", //italic斜体 oblique倾斜 font ...

  5. Python----递归------Eight Queens 八皇后问题

    递归思想是算法编程中的重要思想. 作为初学者,对递归编程表示很蒙逼,每次遇到需要递归的问题,心里就有一万头草泥马飞过~~~~~~(此处略去一万头草泥马) 在B站看数据结构与算法的视频时,视频中给了两个 ...

  6. JS对象中,在原型链上找到属性后 最终将值拷贝给原对象 而不是引用

    遇到一个面试题 要求写一个函数A,每次进行new操作时候能输出2,3,4,5... new A() // 输出2 new A() // 输出3 new A() // 输出4 function A() ...

  7. Oracle最大游标数控制

    /************************************************************************ ********* Oracle最大游标数控制 ** ...

  8. C/C++ 中野指针产生的问题

    野指针产生的问题: 野指针的定义: > 野指针是指:指向一个已删除的对象或未申请访问受限内存区域的指针.与空指针不同,野指针无法通过简单地判断是否为NULL避免,而只能通过养成良好的编程习惯来尽 ...

  9. 18/10/19 周五欢乐赛题解(c++版)

    注意本题解并没有去追求最优解,只是用比较暴力的方法求解.D题听说要改说明不是位数30位,目前除了D题可能有问题之外其他代码已经全部正确. A.查找字串 用string BF(暴力求解即可) 代码 #i ...

  10. Laradock 快速搭建PHP开发环境

    可能你并不清楚 Docker 是什么,更不了解 Laradock是什么,送上语句自己特别喜欢的一句话 Use Docker First And Learn About It Later 大概意思就是 ...