bzoj1930
一开始我觉得这不是一个弱弱的费用流吗?
每个豆豆拆点,入点出点随便连连
由于肯定是DAG图,边权为正的最大费用肯定能增广出来
于是我们只要跑总流量为2的最大费用最大流不就行了吗
但是
这样会TLE,因为会出现稠密图,spfa跑稠密图太慢
既然这样,能不能换一个找增广路的方法呢?
最大路径更快的方法就是DAG图的拓扑排序+dp
但好像无法处理反向弧导致带来的环啊
那既然这样,反正总流量很小,
我们可以用DAG解决最大路径特有的dp找第一条增广路(因为这时候是肯定的DAG),跑出一个较大费用
然后再用spfa增广呢?这样就大大减小了时间复杂度
这就是AC方法
注意这道题空间卡的较紧,能开integer不要开longint
实现起来要小心
const mo=;
type node=record
next:longint;
point,flow,cost:integer;
end; var edge:array[..] of node;
v:array[..] of boolean;
d,rd,pre,pref:array[..] of integer;
q:array[..] of integer;
p,x,y,cur:array[..] of longint;
len:longint;
max,s,t,i,j,n,m,be:integer; procedure add(x,y,f,c:integer);
begin
edge[len].point:=y;
edge[len].flow:=f;
edge[len].cost:=c;
edge[len].next:=p[x];
p[x]:=len;
end; procedure preflow;
var x,y,f,r,i,j:longint;
begin
r:=;
f:=;
q[]:=s;
while f<=r do //拓扑排序
begin
x:=q[f];
i:=p[x];
while i<>- do
begin
y:=edge[i].point;
dec(rd[y]);
if (rd[y]=) then
begin
inc(r);
q[r]:=y;
end;
i:=edge[i].next;
end;
inc(f);
end;
fillchar(d,sizeof(d),);
d[s]:=;
for j:= to r do //DAG图根据拓扑的顺序dp解决最大路径
begin
x:=q[j];
i:=p[x];
while i<>- do
begin
y:=edge[i].point;
if d[y]<d[x]+ then
begin
d[y]:=d[x]+;
pre[y]:=x;
cur[y]:=i;
if d[y]>d[max] then max:=y;
end;
i:=edge[i].next;
end;
end;
end; procedure change; //建立预处理后的网络继续增广
var i,j,e,w:longint;
begin
for i:= to n do
pref[i]:=;
i:=max;
while i<>s do //相当于找到第一条增广路然后弄一弄反向弧什么的
begin
pref[i]:=;
j:=cur[i];
dec(edge[j].flow);
if pre[i]=s then w:=i;
i:=pre[i];
end;
len:=-;
for i:= to n do
for j:= to n do
if (i<>j) then
if (x[i]<=x[j]) and (y[i]<=y[j]) then
begin
inc(len);
edge[len].point:=j+n;
inc(len);
add(j+n,i,-edge[len-].flow,) //添加原来没加的反向弧
end; p[s]:=-;
for i:= to n do //下面很多处理的细节,不赘述,繁杂但不难想到
begin
if i=w then e:= else e:=;
inc(len);
add(s,i+n,e,);
inc(len);
add(i+n,s,-e,);
end;
// 表示超级源点,s表示起点,t表示超级汇点
t:=*n+;
inc(len);
add(,s,,);
inc(len);
add(s,,,);
for i:= to n do
begin
inc(len);
add(i+n,i,pref[i],);
inc(len);
add(i,i+n,-pref[i],-);
if max=i then e:=
else e:=;
inc(len);
add(i,t,e,);
inc(len);
add(t,i,-e,);
end;
end; function spfa:boolean;
var f,r,x,y,i,j,head,tail:longint;
begin
fillchar(v,sizeof(v),false);
for i:= to t do
d[i]:=-mo;
d[]:=;
q[]:=;
f:=;
r:=;
head:=;
tail:=;
while head<=tail do //缩空间的写法,好久没这么写了
begin
x:=q[f];
v[x]:=false;
i:=p[x];
while i<>- do
begin
y:=edge[i].point;
if edge[i].flow> then
begin
if d[x]+edge[i].cost>d[y] then
begin
d[y]:=edge[i].cost+d[x];
pre[y]:=x;
cur[y]:=i;
if not v[y] then
begin
v[y]:=true;
r:=(r+) mod mo;
inc(tail);
q[r]:=y;
end;
end;
end;
i:=edge[i].next;
end;
f:=(f+) mod mo;
inc(head);
end;
if d[t]=-mo then exit(false) else exit(true);
end; function mincost:longint; //最大费用最大流
var i,j:longint;
begin
be:=d[max];
mincost:=be; //预处理出来的费用
while spfa do
begin
mincost:=mincost+d[t];
i:=t;
while i<> do
begin
j:=cur[i];
dec(edge[j].flow);
inc(edge[j xor ].flow);
i:=pre[i];
end;
end;
end; begin
len:=-;
fillchar(p,sizeof(p),);
readln(n);
for i:= to n do
readln(x[i],y[i]);
for i:= to n do
for j:= to n do
if (i<>j) then
if (x[i]<=x[j]) and (y[i]<=y[j]) then
begin
len:=len+;
add(i,j,,); //个人感觉这样建之后添加边更容易一点
inc(rd[j]);
end; s:=*n+;
for i:= to n do
if rd[i]= then
begin
len:=len+;
add(s,i,,);
inc(rd[i]);
end; preflow;
change;
writeln(mincost);
end.
bzoj1930的更多相关文章
- 【BZOJ1930】[Shoi2003]pacman 吃豆豆 最大费用最大流
[BZOJ1930][Shoi2003]pacman 吃豆豆 Description 两个PACMAN吃豆豆.一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方.PACMAN走到豆豆处就会 ...
- BZOJ1930 [Shoi2003]pacman 吃豆豆
dp,首先建出图,f[i][j]表示a吃到了i点,b吃到了j点的最大值,转移的时候转移拓扑序小的那一维,如果i拓扑序小于j,那么转移到f[k][j],否则转移到f[i][k],建出的图边数也要优化, ...
- 【BZOJ1930】【SHOI2003】吃豆豆
初见杀…… 原题: 两个PACMAN吃豆豆.一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方.PACMAN走到豆豆处就会吃掉它.PACMAN行走的路线很奇怪,只能向右走或者向上走,他们行 ...
- [转载]hzwer的bzoj题单
counter: 664BZOJ1601 BZOJ1003 BZOJ1002 BZOJ1192 BZOJ1303 BZOJ1270 BZOJ3039 BZOJ1191 BZOJ1059 BZOJ120 ...
- BZOJ刷题列表【转载于hzwer】
沿着黄学长的步伐~~ 红色为已刷,黑色为未刷,看我多久能搞完吧... Update on 7.26 :之前咕了好久...(足见博主的flag是多么emmm......)这几天开始会抽时间刷的,每天几道 ...
随机推荐
- 21_resultMap和resultType总结
[resultType] [ 作用 ] 将查询结果按照SQL列名与pojo属性名一致性 映射到pojo中. [ 使用场合 ] 常见的一些明细记录的展示,比如用户购买商品的明细,将关联查询信息全部展示在 ...
- Linux中的磁盘
Linux的磁盘管理 (很重要请注意高能预警) 硬盘:几个盘片,双面,磁性颗粒, 处理速率不同步:借助于一个中间层 文件系统(FileSystem) 可以实现对磁盘行的文件进行读写 文 ...
- php 调用 webservice服务
class data{ $a = 123; $b = 456; } //直接php的SoapClient类 $client = new SoapClient('http://xxx.com/xx.as ...
- Mac OS X平台上Java环境的配置
最近换了工作,以前是做c/c++的,但是现在公司的主打产品是使用Java开发,为了以后维护代码,现在开始抽空学习一下Java相关的内容. 在学习之前,首先需要搭建各种平台的开发环境,而我选用的操作系统 ...
- 前端资源多个产品整站一键打包&包版本管理(三)—— gulp分流
问题: 当我们一个工作台里面有好几个项目的时候,我们要为项目的前端资源进行打包,但是,gulpfile只有一个,如果我们把所有的打包都放在同一个文件里面,首先文件会越来越大,而且不便于管理,这时,我们 ...
- 11个有用的Linux命令
Linux命令行吸引了大多数Linux爱好者.一个正常的Linux用户一般掌握大约50-60个命令来处理每日的任务.今天为你解释下面几个命令:sudo.python.mtr.Ctrl+x+e.nl.s ...
- Python和C++交互
关键字:Python 2.7,VS 2010,swig OS:Win8.1 with update. 1.下载swig:http://www.swig.org/download.html 2.将swi ...
- makefile的简单写法
makefile 使用方法: vi 一个Makefile文件 CC = g++ // 指的是用什么编译器RM = rm -rf // 定义一个删除的指令(变量)CFLAGS = -c -Wal ...
- 关于Mysql数据库longblob格式数据的插入com.mysql.jdbc.PreparedStatement.setBinaryStream(ILjava/io/InputStream;J)V问题分析
当数据库字段为blob类型时 ,我们如果使用PreparedStatement中的setBinaryStream(int,InputStream,int)方法需要注意 在向blob字段类型中插入数据时 ...
- RedHat和CentOS使用本地yum源配置
2013-04-01 11:38:30 标签:本地yum源 版权声明:原创作品,谢绝转载!否则将追究法律责任. 使用yum命令安装所需的软件,如果设备网络状况很好,当然也没必要去配置本地yum源,直接 ...