我们先处理出每一条边会对花费产生几次贡献。然后把每一条边按照:进行一次操作减去的花费,从大到小放出大根堆中。不断取出堆中最大,减去变小的贡献,然后重新放入贡献变小后的这个元素。直至符合条件。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int T,n,s,u,v,w,ans,sum;
int size[N];
int cnt,head[N];
struct edge{
int next,to,w,t;}e[N<<1];
struct node
{
int t,w,v;
inline bool operator < (const node &x) const
{
return x.v>v;
}
};
inline void add(int u,int v,int w)
{
cnt++;
e[cnt].next=head[u];
e[cnt].to=v;
e[cnt].w=w;
e[cnt].t=0;
head[u]=cnt;
}
void dfs(int u,int fa)
{
bool jay=true;
for (register int i=head[u]; i; i=e[i].next)
if (e[i].to!=fa)
{
jay=false;
dfs(e[i].to,u);
e[i].t=size[e[i].to];
size[u]+=size[e[i].to];
}
if (jay) size[u]=1;
}
priority_queue<node>q;
signed main(){
scanf("%lld",&T);
while (T--)
{
scanf("%lld%lld",&n,&s);
sum=0;
while (q.size()) q.pop();
cnt=0;
for (register int i=1; i<=n; ++i) head[i]=0;
for (register int i=1; i<=n; ++i) size[i]=0;
for (register int i=1; i<n; ++i)
{
scanf("%lld%lld%lld",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
dfs(1,0);
for (register int i=1; i<=cnt; ++i)
if (e[i].t)
{
sum+=e[i].t*e[i].w;
int del=(e[i].w-e[i].w/2)*e[i].t;
q.push((node){
e[i].t,e[i].w/2,del});
}
ans=0;
while (sum>s)
{
node u=q.top(); q.pop();
sum-=u.v;
int del=(u.w-u.w/2)*u.t;
q.push((node){
u.t,u.w/2,del});
ans++;
}
printf("%lld\n",ans);
}
return 0;
}