题解 P3006 【[USACO11JAN]瓶颈Bottleneck】
bztMinamoto · · 题解
打广告->这里
感觉这题的思路还是挺不错的。然而为啥全网就一个题解而且只有代码……然后我只好看着代码理解了好久……
题意就是有一棵树,每一个节点向他父亲节点连边,且有一个容量表示每一秒可以经过的牛的数量,每一个点有一堆牛,在满足容量限制的情况下可以不断往祖先跳直到跳到1节点。然后问你在保证总时间最短的情况下第
首先,不难发现一个贪心,就是如果向父亲的边能够流满的时候,流满一定比不流满优
那么我们令每一条边都强制流满,然后对每个点记录一个值
那么我们设每一个节点开始时牛的个数为
那么令
那么,我们对询问按时间排序。当询问的时间大于当前
然后总不可能维护时间轴……所以开个优先队列把所有点的
讲的应该还蛮清楚的吧……
// luogu-judger-enable-o2
//minamoto
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
inline ll read(){
#define num ch-'0'
char ch;bool flag=0;ll res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*10+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[1<<21],z[20];int C=-1,Z;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
inline void print(ll x){
if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=100005;
struct query{ll t,res;int id;}ask[N];
inline bool cmp1(query x,query y){return x.t<y.t;}
inline bool cmp2(query x,query y){return x.id<y.id;}
struct node{
ll t;int x;node(){}
node(ll t,int x):t(t),x(x){}
inline bool operator <(const node &b)const
{return t>b.t;}
};
priority_queue<node> q;
int fa[N],f[N],lim[N];ll cow[N],pass[N];
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
int n,m;
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read();
for(int i=1;i<=n;++i) fa[i]=i;
for(int i=2;i<=n;++i)
f[i]=read(),cow[i]=read(),lim[i]=read(),pass[f[i]]-=lim[i],pass[i]+=lim[i];
for(int i=1;i<=m;++i)
ask[i].t=read(),ask[i].id=i;
sort(ask+1,ask+1+m,cmp1);
for(int i=2;i<=n;++i)
if(pass[i]>0)
q.push(node(cow[i]/pass[i],i));
int l=1,x,tp;
while(!q.empty()&&l<=m){
while(l<=m&&ask[l].t<=q.top().t)
ask[l].res=cow[1]-pass[1]*ask[l].t,++l;
if(fa[q.top().x]!=q.top().x){q.pop();continue;}
x=q.top().x,tp=find(f[x]),cow[tp]+=cow[x];
pass[tp]+=pass[x],fa[x]=tp;
if(pass[tp]>0) q.push(node(cow[tp]/pass[tp],tp));
q.pop();
}
sort(ask+1,ask+1+m,cmp2);
for(int i=1;i<=m;++i) print(ask[i].res);
Ot();
return 0;
}