博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷P3006 [USACO11JAN]瓶颈Bottleneck(堆模拟)
阅读量:5163 次
发布时间:2019-06-13

本文共 2827 字,大约阅读时间需要 9 分钟。

 

感觉这题的思路还是挺不错的。然而为啥全网就一个题解而且只有代码……然后我只好看着代码理解了好久……

题意就是有一棵树,每一个节点向他父亲节点连边,且有一个容量表示每一秒可以经过的牛的数量,每一个点有一堆牛,在满足容量限制的情况下可以不断往祖先跳直到跳到1节点。然后问你在保证总时间最短的情况下第$t$秒1节点有多少头牛

首先,不难发现一个贪心,就是如果向父亲的边能够流满的时候,流满一定比不流满优

那么我们令每一条边都强制流满,然后对每个点记录一个值$pass[i]$,值为它能向父亲流的最大的流量减去它的儿子们向它流的最大流量,不难发现它代表如果每条边都流满之后每秒能有多少头牛离开这个点向祖先去。

那么我们设每一个节点开始时牛的个数为$cow[i]$,那么,$cow[i]/pass[i]$就代表这一个节点的所有牛都走光所需要的时间

那么令$t=cow[i]/pass[i]$,当时间小于等于$t$的时候,我们需要考虑这一个点还剩下多少头牛。当时间大于$t$的时候,我们已经不需要再考虑这个点还剩下多少头牛了,因为可以在满流之后让它所有的牛都到它的父亲那里去。那么,我们可以把它和它的父亲看做同一个点,牛的数量为两个点之和,$pass[fa[i]]$也是两个点之和(它和父亲之间的那条边的流量因为父亲减一次它加一次已经抵消了),然后再对这个点记录一个新的$t$就好了。这个可以用一个并查集维护

那么,我们对询问按时间排序。当询问的时间大于当前$t$的时候,我们把所有$t$小于等于询问的时间的点全都和它的父亲给并起来。当询问的时间小于等于当前$t$时,答案就是$cow[1]+pass[1]*询问的时间$($cow[1]$代表所有已经被缩到这一个点的总的牛的数量,然后1点的pass肯定是负数,所以减去就相当于加上这个点的儿子的点全都满流向它流,在询问的这段时间里能流多少)

然后总不可能维护时间轴……所以开个优先队列把所有点的$t$给扔进去就好了,反正就这些点的$t$有用

讲的应该还蛮清楚的吧……

1 // luogu-judger-enable-o2 2 //minamoto 3 #include
4 #include
5 #include
6 #include
7 #include
8 #define ll long long 9 using namespace std;10 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)11 char buf[1<<21],*p1=buf,*p2=buf;12 inline ll read(){13 #define num ch-'0'14 char ch;bool flag=0;ll res;15 while(!isdigit(ch=getc()))16 (ch=='-')&&(flag=true);17 for(res=num;isdigit(ch=getc());res=res*10+num);18 (flag)&&(res=-res);19 #undef num20 return res;21 }22 char sr[1<<21],z[20];int C=-1,Z;23 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}24 inline void print(ll x){25 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;26 while(z[++Z]=x%10+48,x/=10);27 while(sr[++C]=z[Z],--Z);sr[++C]='\n';28 }29 const int N=100005;30 struct query{ll t,res;int id;}ask[N];31 inline bool cmp1(query x,query y){
return x.t
b.t;}38 };39 priority_queue
q;40 int fa[N],f[N],lim[N];ll cow[N],pass[N];41 int find(int x){42 return fa[x]==x?x:fa[x]=find(fa[x]);43 }44 int n,m;45 int main(){46 // freopen("testdata.in","r",stdin);47 n=read(),m=read();48 for(int i=1;i<=n;++i) fa[i]=i;49 for(int i=2;i<=n;++i)50 f[i]=read(),cow[i]=read(),lim[i]=read(),pass[f[i]]-=lim[i],pass[i]+=lim[i];51 for(int i=1;i<=m;++i)52 ask[i].t=read(),ask[i].id=i;53 sort(ask+1,ask+1+m,cmp1);54 for(int i=2;i<=n;++i)55 if(pass[i]>0)56 q.push(node(cow[i]/pass[i],i));57 int l=1,x,tp;58 while(!q.empty()&&l<=m){59 while(l<=m&&ask[l].t<=q.top().t)60 ask[l].res=cow[1]-pass[1]*ask[l].t,++l;61 if(fa[q.top().x]!=q.top().x){q.pop();continue;}62 x=q.top().x,tp=find(f[x]),cow[tp]+=cow[x];63 pass[tp]+=pass[x],fa[x]=tp;64 if(pass[tp]>0) q.push(node(cow[tp]/pass[tp],tp));65 q.pop();66 }67 sort(ask+1,ask+1+m,cmp2);68 for(int i=1;i<=m;++i) print(ask[i].res);69 Ot();70 return 0;71 }

 

转载于:https://www.cnblogs.com/bztMinamoto/p/9622691.html

你可能感兴趣的文章
超级强大的鼠标手势工具
查看>>
常用Dockerfile举例
查看>>
jquery的ajax用法
查看>>
设计模式-策略模式(Strategy)
查看>>
django orm 数据查询详解
查看>>
JarvisOJ Basic 熟悉的声音
查看>>
C# list导出Excel(二)
查看>>
CAS 单点登录模块学习
查看>>
跟着辛星用PHP的反射机制来实现插件
查看>>
Android应用开发-网络编程①
查看>>
input中的name,value以及label中的for
查看>>
静态库制作-混编(工程是oc为基础)
查看>>
jQuery 显示加载更多
查看>>
代理模式
查看>>
Confluence 6 系统运行信息中的 JVM 内存使用情况
查看>>
Confluence 6 升级以后
查看>>
用JS实现版面拖拽效果
查看>>
二丶CSS
查看>>
《avascript 高级程序设计(第三版)》 ---第二章 在HTML中使用Javascript
查看>>
JS一些概念知识及参考链接
查看>>