Codeforces Round #661 (Div. 3) E1-Weights Division (easy version)-Greedy, priority queue, tree

Title description :
Insert picture description here
Question meaning :
give you a tree, each edge has
a weight , find sum: the path from the leaf node to all other nodes and give you another operation: halve the weight of any edge, ask The smallest number of operands makes sum<=k (given by k)

Ideas :
1. How to find sum
can calculate the number of times each edge is used leaf, then sum+=a[i].w*leaf, calculate the contribution of each edge
2. How to minimize the number of operations
so that sum becomes less than or equal to k, and the number of operations is the least. You can start to change with the larger edge, which will make the sum closer to
the contribution of k edge (a[i].wa[i].w/2)*leaf

Code

struct edge {
    
    
	ll u,v,w,next;
} a[maxn];
struct node {
    
    
	ll val,leaf;
	friend	bool operator < (node x, node y) {
    
    
		return (x.val-x.val/2)*x.leaf<(y.val-y.val/2)*y.leaf;
	}
};
ll n,k,head[maxn],cnt,sum,ans;
void add(ll u,ll v,ll w) {
    
    
	a[cnt].u=u;
	a[cnt].v=v;
	a[cnt].w=w;
	a[cnt].next=head[u];
	head[u]=cnt++;
}
priority_queue<node>q;
ll  dfs(ll u,ll p) {
    
    
	ll le=0;
	for(int i=head[u]; ~i; i=a[i].next) {
    
    
		ll v=a[i].v;
		if(v==p) continue;
		ll temp=dfs(v,u);
		q.push({
    
    a[i].w,temp});
		sum+=a[i].w*temp;
		le+=temp;
	}
	return le?le:1;
}
int main() {
    
    
	int toto=read();
	while(toto--) {
    
    
		n=read(),k=read();
		sum=ans=cnt=0;
		while(q.size()) q.pop();
		mst(head,-1);
		for(int i=1 ; i<n ; i++) {
    
    
			ll u=read();
			ll v=read();
			ll w=read();
			add(u,v,w);
			add(v,u,w);
		}
		dfs(1,0);
		while(sum>k) {
    
    
			ans++;
			node fr=q.top();
			q.pop();
			sum-=(fr.val-fr.val/2)*fr.leaf;
			node temp;
			temp.val=fr.val/2;
			temp.leaf=fr.leaf;
			q.push(temp);
		}
		cout<<ans<<endl;
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/wmy0536/article/details/107843968