以根为原点,所有叶子为汇点建立网络。

对于一条边$(x,y,A,B)$,$x$向$y$连边,容量$A$,费用0,再连边,容量$B-A$,费用1。

然后不断增广,直到费用达到$M$为止的最大流即为答案。

考虑用树链剖分+线段树来模拟这个过程:

首先加入所有费用为0的边,每次求出到根距离最小的可增广的叶子,然后求出路径上容量的最小值,将所有边的容量减掉它。

如果减的过程中有边容量变为0,那么将它加入临时数组$q$中。

然后扫描$q$中所有边,如果一条边之前费用为0,那么把它容量设置为$B-A$,然后将子树内费用都加一,否则将它子树内的点都标记为不可增广。

时间复杂度$O(n\log^2n)$。

#include<cstdio>
const int N=10010,M=33000,inf=~0U>>1;
int n,m,i,x,y,A,B,ans,cnt,q[N],mf[M],mc[M],tf[M],tc[M],td[M];
int g[N],v[N],nxt[N],f[N],d[N],wa[N],wb[N],size[N],son[N],top[N],st[N],en[N],dfn,seq[N],S[N];
void dfs(int x){
size[x]=1;son[x]=-1;
for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
d[v[i]]=d[x]+1;dfs(v[i]);size[x]+=size[v[i]];
if(son[x]<0||size[v[i]]>size[son[x]])son[x]=v[i];
}
}
void dfs2(int x,int y){
seq[st[x]=++dfn]=x;top[x]=y;
if(~son[x])dfs2(son[x],y);
for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs2(v[i],v[i]);
en[x]=dfn;
}
inline int min(int a,int b){return a<b?a:b;}
inline void tagf(int x,int y){mf[x]-=y;tf[x]+=y;}
inline void tagc(int x,int y){if(mc[x]<inf)mc[x]+=y;tc[x]+=y;}
inline void tagd(int x){mc[x]=inf;tc[x]=0;td[x]=1;}
inline void pb(int x){
if(tf[x])tagf(x<<1,tf[x]),tagf(x<<1|1,tf[x]),tf[x]=0;
if(tc[x])tagc(x<<1,tc[x]),tagc(x<<1|1,tc[x]),tc[x]=0;
if(td[x])tagd(x<<1),tagd(x<<1|1),td[x]=0;
}
inline void up(int x){
mf[x]=min(mf[x<<1],mf[x<<1|1]);
mc[x]=min(mc[x<<1],mc[x<<1|1]);
}
void build(int x,int a,int b){
if(a==b){
int y=seq[a];
mf[x]=wa[y];
if(size[y]>1)mc[x]=inf;
return;
}
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid+1,b),up(x);
}
void modifyf(int x,int a,int b,int c,int p){
if(a==b){mf[x]=p;return;}
pb(x);
int mid=(a+b)>>1;
if(c<=mid)modifyf(x<<1,a,mid,c,p);else modifyf(x<<1|1,mid+1,b,c,p);
up(x);
}
void changef(int x,int a,int b,int c,int d,int p){
if(c<=a&&b<=d&&mf[x]>p){tagf(x,p);return;}
if(a==b){
q[++cnt]=seq[a];
mf[x]=0;
return;
}
pb(x);
int mid=(a+b)>>1;
if(c<=mid)changef(x<<1,a,mid,c,d,p);
if(d>mid)changef(x<<1|1,mid+1,b,c,d,p);
up(x);
}
void changec(int x,int a,int b,int c,int d){
if(c<=a&&b<=d){tagc(x,1);return;}
pb(x);
int mid=(a+b)>>1;
if(c<=mid)changec(x<<1,a,mid,c,d);
if(d>mid)changec(x<<1|1,mid+1,b,c,d);
up(x);
}
void changed(int x,int a,int b,int c,int d){
if(c<=a&&b<=d){tagd(x);return;}
pb(x);
int mid=(a+b)>>1;
if(c<=mid)changed(x<<1,a,mid,c,d);
if(d>mid)changed(x<<1|1,mid+1,b,c,d);
up(x);
}
int askmf(int x,int a,int b,int c,int d){
if(c<=a&&b<=d)return mf[x];
pb(x);
int mid=(a+b)>>1,t=inf;
if(c<=mid)t=askmf(x<<1,a,mid,c,d);
if(d>mid)t=min(t,askmf(x<<1|1,mid+1,b,c,d));
return up(x),t;
}
inline int getmc(){
int x=1,a=2,b=dfn,mid;
while(a<b){
mid=(a+b)>>1;
if(mc[x<<1]<mc[x<<1|1])x<<=1,b=mid;else x=x<<1|1,a=mid+1;
}
return seq[a];
}
inline int getmf(int x){
int t=inf;
while(top[x])t=min(t,askmf(1,2,dfn,st[top[x]],st[x])),x=f[top[x]];
if(st[x]>=2)t=min(t,askmf(1,2,dfn,2,st[x]));
return t;
}
inline void chain(int x,int y){
cnt=0;
while(top[x])changef(1,2,dfn,st[top[x]],st[x],y),x=f[top[x]];
if(st[x]>=2)changef(1,2,dfn,2,st[x],y);
while(cnt){
x=q[cnt--];
if(!S[x]&&wb[x]>wa[x])modifyf(1,2,dfn,st[x],wb[x]-wa[x]),changec(1,2,dfn,st[x],en[x]);
else changed(1,2,dfn,st[x],en[x]);
S[x]++;
}
}
int main(){
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d%d%d%d",&x,&y,&A,&B);
v[i]=y,nxt[i]=g[x],g[x]=i;
f[y]=x,wa[y]=A,wb[y]=B;
}
dfs(0),dfs2(0,0),build(1,2,dfn);
while(mc[1]<inf){
y=getmf(x=getmc());
if(mc[1]*y>m)y=m/mc[1];
if(!y)break;
m-=mc[1]*y;
ans+=y;
chain(x,y);
}
return printf("%d",ans),0;
}

  

BZOJ2040 : [2009国家集训队]拯救Protoss的故乡的更多相关文章

  1. BZOJ2040[2009国家集训队]拯救Protoss的故乡——模拟费用流+线段树+树链剖分

    题目描述 在星历2012年,星灵英雄Zeratul预测到他所在的Aiur行星在M天后会发生持续性暴雨灾害,尤其是他们的首都.而Zeratul作为星灵族的英雄,当然是要尽自己最大的努力帮助星灵族渡过这场 ...

  2. BZOJ 2039: [2009国家集训队]employ人员雇佣

    2039: [2009国家集训队]employ人员雇佣 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 1369  Solved: 667[Submit ...

  3. BZOJ 2038: [2009国家集训队]小Z的袜子(hose) [莫队算法]【学习笔记】

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 7687  Solved: 3516[Subm ...

  4. BZOJ 2038: [2009国家集训队]小Z的袜子(hose)

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 7676  Solved: 3509[Subm ...

  5. 莫队算法 2038: [2009国家集训队]小Z的袜子(hose)

    链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2038 2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 ...

  6. BZOJ 2038 [2009国家集训队]小Z的袜子 莫队

    2038: [2009国家集训队]小Z的袜子(hose) 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=2038 Descriptionw ...

  7. Bzoj 2038: [2009国家集训队]小Z的袜子(hose) 莫队,分块,暴力

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 5763  Solved: 2660[Subm ...

  8. BZOJ2038: [2009国家集训队]小Z的袜子(hose) -- 莫队算法 ,,分块

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 3577  Solved: 1652[Subm ...

  9. BZOJ 2038: [2009国家集训队]小Z的袜子(hose) ( 莫队 )

    莫队..先按sqrt(n)分块, 然后按块的顺序对询问排序, 同块就按右端点排序. 然后就按排序后的顺序暴力求解即可. 时间复杂度O(n1.5) --------------------------- ...

随机推荐

  1. 在Linux中安装JDK的步骤

    相信不少学习Java的朋友都在Windows操作系统中安装过JDK,这里就不对JDK做详细的介绍了. 在Windows下安装JDK可参考:JDK的安装和配置 1.下载JDK 我们可以去官网(http: ...

  2. Swift - 状态栏颜色显示(字体、背景)

    ios上状态栏 就是指的最上面的20像素高的部分 状态栏分前后两部分,要分清这两个概念,后面会用到: 前景部分:就是指的显示电池.时间等部分: 背景部分:就是显示黑色或者图片的背景部分: 如下图:前景 ...

  3. Swift - 获取、改变按钮的标题文本(UIButton点击切换title)

    在开发中,我们常常需要动态地改变按钮标签文字,使用 setTitle() 函数就可以了.有时我们需要在几个标题间切换,比如下面样例所示,按钮点击后按钮文字会在"播放""暂 ...

  4. AngularJS 服务(Service)

    AngularJS 中你可以创建自己的服务,或使用内建服务. 什么是服务? 在 AngularJS 中,服务是一个函数或对象,可在你的 AngularJS 应用中使用. AngularJS 内建了30 ...

  5. 重温WCF之消息契约(MessageContract)(六)

    对于SOAP来说主要由两部分构成Header和Body,他们两个共同构成了SOAP的信封,通常来说Body保存具体的数据内容,Header保存一些上下文信息或关键信息.比如:在一些情况下,具有这样的要 ...

  6. Delphi之DLL知识学习4---创建DLL

    下面是在Delphi中创建一个DLL的全过程,你将看到怎样创建一个接口单元,使之可以被其他的应用程序访问.并且将学会怎么把Delphi的窗体加入DLL中. 一.数美分:一个简单的DLL 下面是包含一个 ...

  7. mac os x使用技巧及常用软件

    常见键盘符号:⌘(command).⌥(option).⇧(shift).⇪(caps lock).⌃(control) 常用快捷键 复制  Command+c / Option+拖拽 粘贴  Com ...

  8. VC++中字符串编码的转换

    在以前VC++6.0中默认的字符集是多字节字符集(MBCS:Multi-Byte Character Set),而VS2005及以后默认的字符集是Unicode,这样导致以前在VC6.0中非常简单实用 ...

  9. Codeforces Round #363 Fix a Tree(树 拓扑排序)

    先做拓扑排序,再bfs处理 #include<cstdio> #include<iostream> #include<cstdlib> #include<cs ...

  10. 攻城狮在路上(叁)Linux(二十一)--- linux磁盘检查 fsck \ badblocks

    若系统掉电或磁盘发生问题,可利用fsck命令对文件系统进行检查.这一步是可选的,尽量少用. 使用前的建议:使用fsck命令时,被检查的分区务必不要挂载在系统上. 一.fsck: 命令格式:fsck [ ...