CF1399E1 Weights Division (easy version)

我们先处理出每一条边会对花费产生几次贡献。然后把每一条边按照:进行一次操作减去的花费,从大到小放出大根堆中。不断取出堆中最大,减去变小的贡献,然后重新放入贡献变小后的这个元素。直至符合条件。
#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;	
}

猜你喜欢

转载自blog.csdn.net/Dove_xyh/article/details/108434360