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

对于一条边$(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. backBarButtonItem 替换

    最上级vc里面加 下级设置生效 UIImage* image = [UIImage imageNamed:@"back_button.png"]; [item setBackBut ...

  2. 从xml中构建sqlSessionFactory

    String resource = "org/mybatis/example/Configuration.xml"; Reader reader = Resources.getRe ...

  3. Swift - 文件目录路径获取及数据储存(Home目录,文档目录,缓存目录)

    iOS应用程序只能在自己的目录下进行文件的操作,不可以访问其他的存储空间,此区域被称为沙盒.   应用沙盒结构分析 1.应用程序包:包含了所有的资源文件和可执行文件 2.Documents:保存应用运 ...

  4. 二、JavaScript语言--JS基础--JavaScript进阶篇--浏览器对象

    1.window对象 window对象是BOM的核心,window对象指当前的浏览器窗口. window对象方法:

  5. Android View -- setTranslationX

    通过此方法使View位置发生偏移,达到margin的作用却又不改变View的getLeft()的值. 恢复方法是setTranslationX(0),而不是上一次偏移量的相反数. 不过,通过getLo ...

  6. 【数据库】 防止sql注入,过滤敏感关键字

    private bool FilterIllegalChar(string sWord) { var result = false; var keyWord = @"select|inser ...

  7. Bootstrap 排版 笔记

    Bootstrap 使用 Helvetica Neue. Helvetica. Arial 和 sans-serif 作为其默认的字体栈. 使用 Bootstrap 的排版特性,您可以创建标题.段落. ...

  8. Linux内核创建一个新进程的过程

    “平安的祝福 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 进程在 ...

  9. Linux学习笔记(2)Linux学习注意事项

    1 学习Linux的注意事项 ① Linux严格区分大小写 ② Linux中所有内容均以文件形式保存,包括硬件,如硬件文件是/deb/sd[a-p] ③ Linux不靠扩展名区分文件类型,但有的文件是 ...

  10. JavaScript入门(2)

    encodeURI()和 decodeURI()作用  编码与解码 encodeURIComponent()和 decodeURIComponent()作用区别是  后者可以处理一些特殊字符进行转义 ...