一类最小割bzoj2127,bzoj2132 bzoj3438
思考一下我们接触的最小割问题
最小割的基本问题(可能会和图论的知识相结合,比如bzoj1266,bzoj1797)
最大权闭合图(bzoj1497)
最大点权覆盖集,最大点权独立集(bzoj1324)
最近接触到了一类关于最小割新的问题,我也不知道叫什么好
反正它有这么几个特点
每个点都有两种选择的可能性,设为属于S和属于T,属于S有收益a[i],属于T有收益b[i]
两点之间可能因为同在一个或不在同一个集合内产生额外的收益
使收益最大化(废话)
大概就是这个意思,如果看不懂也没关系,我们先从最简单的问题开始分析
首先在满足1的条件下,我们有m对关系,点i和j若同在一个集合,那么就能产生一个额外收益w[i,j];
最终使收益最大化。
对此,我们对于每个点i,我们连s--->i 流量为a[i], i--->t 流量为b[i];
然后对于每对关系(i,j),连i<---j,j--->i 流量都为w[i,j];
然后怎么做呢?根据割的定义,就是s到t没有路
在这里就是,割完之后每个点要么和s连,要么和t连;
我们假如以两个点的图为例,思考一下最小割可能割掉的边(我比较懒,就不发图了)
就会发现,这里的最小割正能使不在一个集合的两个点之间的边被切断
或者使在一个集合的两个点之间的边不被切断
最终ans=∑a[i]+∑b[i]+∑w[i,j]-mincut
这里割对应一种解决问题的方案
好这是最初步,下面就是bzoj2132的问题,
条件2变成了,不在同一个集合里的两点会产生一个额外的收益
我们先按基本问题的方式建图
有了最开始的经验,我们不难猜测,
假如选择一个点集,使其中的点i,颠倒一下使s-->i的流量为b[i],i-->t的流量为a[i];
这样我们再做最小割,不就又变回了最基本的问题吗?
而我们应该怎么选择点集呢?
显然,这个点集内部的点是不能有关系的,并且,这些点是给出关系中一侧的点;
说的明确一点,就是不管S,T,根据关系建得的图G,必须是一个二分图;
那么这道题满不满足呢?
我们对平面图黑白相间染色,显然黑点与白点才会产生关系,
黑点与黑点,白点与白点之间是没有关系——是二分图!
于是这道题就简单了!
const dx:array[..] of integer=(,,,-);
dy:array[..] of integer=(,-,,);
inf=; type node=record
point,next,flow:longint;
end; var edge:array[..] of node;
p,cur,h,numh,pre:array[..] of longint;
c,num:array[..,..] of longint;
s,x,y,i,j,k,n,m,len,t:longint; procedure add(x,y,f:longint);
begin
inc(len);
edge[len].flow:=f;
edge[len].point:=y;
edge[len].next:=p[x];
p[x]:=len;
end; begin
len:=-;
fillchar(p,sizeof(p),);
readln(n,m);
t:=n*m+;
for i:= to n do
for j:= to m do
begin
inc(k);
num[i,j]:=k;
read(x);
s:=s+x;
if (i+j) mod = then //黑白染色
begin
add(,k,x);
add(k,,x);
end
else begin
add(k,t,x);
add(t,k,);
end;
end; for i:= to n do
for j:= to m do
begin
read(x);
s:=s+x;
if (i+j) mod = then
begin
add(num[i,j],t,x);
add(t,num[i,j],x);
end
else begin
add(,num[i,j],x);
add(num[i,j],,);
end;
end;
for i:= to n do
for j:= to m do
read(c[i,j]);
for i:= to n do
for j:= to m do
for k:= to do
begin
x:=i+dx[k];
y:=j+dy[k];
if num[x,y]> then
begin
s:=s+c[i,j];
add(num[i,j],num[x,y],c[i,j]+c[x,y]); //两地建筑物类型不同,增加的额外收益是相互的,一荣俱荣一损俱损
add(num[x,y],num[i,j],);
end;
end;
writeln(s-sap); //求最大流省略
end.
2132
下面再扩展这个问题
条件2变为若点i,j同属于S,增加额外收益为w[i,j],
若点i,j同属于T,增加额外收益为r[i,j]; (这就是bzoj2127)
我们对于每个点i,我们连s--->i 流量为a[i], i--->t 流量为b[i];
显然,之前根据关系的建图方法已经不适用了,我们要思考怎么解决同属于S,同属于T所带来的收益
这必须得回到割的意义上来,我们知道割表示损失,我们取不到的
那我们就来分析一下损失:
1. 当i和j同时属于S的时候,我们损失了r[i,j]
2. 当i和j同时属于T的时候,我们损失了w[i,j]
3. 当i,j属于不同的集合,我们损失了w[i,j]+r[i,j]
这有什么用呢?我们可以换一种方式表达
当i属于S时,损失了r[i,j]/2,当j属于S时,损失了r[i,j]/2
当i属于T时,损失了w[i,j]/2,当j属于T时,损失了w[i,j]/2
这样我们再看3,我们还要在增加(w[i,j]+r[i,j])/2的损失
不难发现,问题又变回了最基本的问题
对于点i,我们增加s--->i 流量为r[i,j]/2,t--->i 流量为w[i,j]/2
对于每对关系(i,j),连i<---j,j--->i 流量都为(w[i,j]+r[i,j])/2;
ans=所有可能收益和-mincut
为了方便,我们可以一开始把流量全乘2,最后再除以2即可
友情提示:这道题不加当前弧优化的sap会TLE
const inf=;
dx:array[..] of integer=(-,,,);
dy:array[..] of integer=(,,-,); type node=record
point,next,flow:longint;
end; var edge:array[..] of node;
d,p,cur,h,numh,pre:array[..] of longint;
a:array[..,..,..] of longint;
num,b,c:array[..,..] of longint;
n,m,t,s,x,i,j,k,len,y:longint; function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end; procedure add(x,y,f:longint);
begin
inc(len);
edge[len].point:=y;
edge[len].flow:=f;
edge[len].next:=p[x];
p[x]:=len;
end; function sap:longint;
var tmp,neck,u,i,j,q:longint;
flag:boolean; begin
numh[]:=t+;
u:=;
sap:=;
cur:=p;
neck:=inf;
while h[]<t do
begin
d[u]:=neck;
flag:=false;
i:=cur[u];
while i<>- do
begin
j:=edge[i].point;
if (edge[i].flow>) and (h[u]=h[j]+) then
begin
flag:=true;
neck:=min(neck,edge[i].flow);
cur[u]:=i;
pre[j]:=u;
u:=j;
if u=t then
begin
sap:=sap+neck;
i:=t;
while i<> do
begin
i:=pre[i];
j:=cur[i];
dec(edge[j].flow,neck);
inc(edge[j xor ].flow,neck);
end;
neck:=inf;
u:=;
end;
break;
end;
i:=edge[i].next;
end;
if not flag then
begin
dec(numh[h[u]]);
if numh[h[u]]= then exit;
tmp:=t;
i:=p[u];
q:=;
while i<>- do
begin
j:=edge[i].point;
if (edge[i].flow>) and (h[j]<tmp) then
begin
q:=i;
tmp:=h[j];
end;
i:=edge[i].next;
end;
cur[u]:=q;
h[u]:=tmp+;
inc(numh[h[u]]);
if u<> then
begin
u:=pre[u];
neck:=d[u];
end;
end;
end;
end; begin
readln(n,m);
len:=-;
fillchar(p,sizeof(p),);
t:=n*m+;
for i:= to n do
begin
for j:= to m do
begin
inc(k);
num[i,j]:=k;
read(x);
s:=s+x;
x:=x shl ;
b[i,j]:=b[i,j]+x;
end;
readln;
end;
for i:= to n do
begin
for j:= to m do
begin
read(x);
s:=s+x;
x:=x shl ;
c[i,j]:=c[i,j]+x;
end;
readln;
end; for i:= to n- do
begin
for j:= to m do
begin
read(x);
s:=s+x;
b[i,j]:=b[i,j]+x;
b[i+,j]:=b[i+,j]+x;
a[i,j,]:=a[i,j,]+x;
a[i+,j,]:=a[i+,j,]+x;
end;
readln;
end; for i:= to n- do
begin
for j:= to m do
begin
read(x);
s:=s+x;
c[i,j]:=c[i,j]+x;
c[i+,j]:=c[i+,j]+x;
a[i,j,]:=a[i,j,]+x;
a[i+,j,]:=a[i+,j,]+x;
end;
readln;
end; for i:= to n do
begin
for j:= to m- do
begin
read(x);
s:=s+x;
b[i,j]:=b[i,j]+x;
b[i,j+]:=b[i,j+]+x;
a[i,j,]:=a[i,j,]+x;
a[i,j+,]:=a[i,j+,]+x;
end;
readln;
end; for i:= to n do
begin
for j:= to m- do
begin
read(x);
s:=s+x;
c[i,j]:=c[i,j]+x;
c[i,j+]:=c[i,j+]+x;
a[i,j,]:=a[i,j,]+x;
a[i,j+,]:=a[i,j+,]+x;
end;
readln;
end;
for i:= to n do
for j:= to m do
begin
for k:= to do
begin
x:=i+dx[k];
y:=j+dy[k];
if num[x,y]> then
begin
add(num[i,j],num[x,y],a[i,j,k]); //注意序号的对应
add(num[x,y],num[i,j],);
end;
end;
add(,num[i,j],b[i,j]);
add(num[i,j],,);
add(num[i,j],t,c[i,j]);
add(t,num[i,j],);
end;
writeln(s-sap div );
end.
2127
这个问题最终阶段是bzoj3438 不再是两点间关系而是多点间关系了
即多个点如果同属A集合会产生一个额外收益c1,同属于B集合会产生一个额外收益c2
这就不能用上述的做法了,具体做法见bzoj3438的解题报告
一类最小割bzoj2127,bzoj2132 bzoj3438的更多相关文章
- 二分图&网络流&最小割等问题的总结
二分图基础: 最大匹配:匈牙利算法 最小点覆盖=最大匹配 最小边覆盖=总节点数-最大匹配 最大独立集=点数-最大匹配 网络流: 技巧: 1.拆点为边,即一个点有限制,可将其转化为边 BZOJ1066, ...
- 【bzoj3894】文理分科 网络流最小割
原文地址:http://www.cnblogs.com/GXZlegend 题目描述 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用 ...
- BZOJ3144 [Hnoi2013]切糕 【最小割】
题目 输入格式 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤ ...
- BZOJ 2039 / Luogu P1791 [2009国家集训队]employ人员雇佣 (最小割)
题面 BZOJ传送门 Luogu传送门 分析 考虑如何最小割建图,因为这仍然是二元关系,我们可以通过解方程来确定怎么建图,具体参考论文 <<浅析一类最小割问题 湖南师大附中 彭天翼> ...
- 【BZOJ2132】圈地计划(最小割)
[BZOJ2132]圈地计划(最小割) 题面 BZOJ 题解 对我而言,不可做!!! 所以我膜烂了ZSY大佬 他的博客写了怎么做... 这,,...太强啦!! 完全想不到黑白染色之后反着连边 然后强行 ...
- 【BZOJ2127】happiness(最小割)
[BZOJ2127]happiness(最小割) 题面 Description 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了, ...
- 【BZOJ3438】小M的作物 最小割
[BZOJ3438]小M的作物 Description 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子 有1个(就是可以种一棵作物)(用1. ...
- 【bzoj2127】happiness 网络流最小割
题目描述 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文 ...
- 【BZOJ2132】圈地计划 最小割
[BZOJ2132]圈地计划 Description 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地. ...
随机推荐
- android 电话拨号器
电话拨号器(重点) 1.产品经理: 需求分析文档,设计原型图 2.UI工程师: 设计UI界面 3.架构师: 写架构,接口文档 4.码农: 服务端,客户端 ...
- 文本框限制输入类型<input>的输入框
最近在开发完一个项目后,又测试人员测试bug,然后我根据他们测试出来的bug一个一个的改,然后就遇到了一个问题,文本框是用来搜索,但是,比如这个文本框是用来搜索年龄的区间,输入条件的时候,如果输入了非 ...
- linux 配置Socks5
1.配置 Socks5 编译环境. yum -y install gcc automake autoconf libtool make 2.安装 Socks5 需要的包. yum -y install ...
- 计算序列中第k小的数
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4046399.html 使用分治算法,首先选择随机选择轴值pivot,并使的序列中比pivot ...
- HTML5的离线储存
在用户没有与因特网连接时,可以正常访问站点或应用,在用户与因特网连接时,更新用户机器上的缓存文件. 原理:HTML5的离线存储是基于一个新建的.appcache文件的缓存机制(不是存储技 ...
- 64位Win8系统下安装Oracle12c
经过3个小时的折腾,终于在64位win8系统下成功安装了Oracle 12c.这篇文章主要把安装过程中遇到的一些问题总结一下,以便帮助后来人参考. 首先我把我的机器的主要配制情况列举出来: 1. 系统 ...
- JS中判断JSON数据是否存在某字段的方法 JavaScript中判断json中是否有某个字段
方式一 !("key" in obj) 方式二 obj.hasOwnProperty("key") //obj为json对象. 实例: var jsonwor ...
- CSS浮动特性总结
1.假设现在CSS中没有浮动(float)属性,那么会变成一个什么样子.我们会发现,目前流行采用浮动方法实现的无论是分栏布局,还是列表排列我们都可以用其他一些CSS属性(不考虑table)代替实现,唯 ...
- css text-overflow溢出文本显示省略号
<div style="width: 100px; overflow: hidden; text-overflow:ellipsis"> <nobr>当对象 ...
- Javascript代码摘录
判断浏览器窗口高度 if (document.documentElement.clientHeight <800) { var elm = document.getElementById('Di ...