E1 - Weights Division (easy version)
题意
给你n个点和最高费用S,然后给你n-1条边,和每条边的边权。让你求如果可以(w_i:=frac{w_i}{2}),需要最少多少步可以满足(costleq S)。
思路
先(dfs)求出每个边的边权和经过每条边的次数。
然后优先队列按{ 如果对这条边进行操作会减少多少元 }从大到小的顺序。
然后贪心即可。
每条边的下面的节点代表的是经过这条边的次数。
每条边的下面的节点代表这条边的权值。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define DOF 0x7f7f7f7f
#define endl '
'
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(case, x) cout << case << " : " << x << endl
#define open freopen("ii.txt", "r", stdin)
#define close freopen("oo.txt", "w", stdout)
#define IO
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0)
#define pb push_back
using namespace std;
#define int long long
#define lson rt << 1
#define rson rt << 1 | 1
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<long long, long long> PII;
const int maxn = 1e6 + 10;
struct edge{
int v,w;
};
vector<vector<edge>>G;
vector<int>val, cnt;
void dfs(int u, int fa = -1) {
if(fa!=-1&&G[u].size()==1)
cnt[u]=1;
for(auto t : G[u]) {
if(t.v == fa)continue;
val[t.v]=t.w;
dfs(t.v, u);
cnt[u] += cnt[t.v];
}
}
struct node{
int cnt,val;
bool operator<(const node t)const{
return val*cnt-(val/2)*cnt<t.val*t.cnt-(t.val/2)*t.cnt;
}
};
void solve() {
int n, s;
cin >> n >> s;
G = vector<vector<edge>>(n + 1);
cnt = val = vector<int>(n + 1);
for(int i = 0; i < n-1; ++i) {
int v, u, w;
cin >> v >> u >> w;
G[v].push_back({u, w});
G[u].push_back({v, w});
}
dfs(1, -1);
priority_queue<node>q;
int sum=0;
for(int i=2;i<=n;++i){
sum+=cnt[i]*val[i];
q.push({cnt[i],val[i]});
}
int ans=0;
while(sum > s) {
++ans; node now=q.top(); q.pop();
sum-=now.val*now.cnt-(now.val/2)*now.cnt;
q.push({now.cnt,now.val/2});
}
cout<<ans<<endl;
}
signed main() {
int t;
cin >> t;
while(t--) {
solve();
}
}