E1. Weights Division (easy version)
题解
请看code
code
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct
{
ll to, val, head, times = 0;
} edge[200005];
ll out[100005] = {0};
ll len = 0;
void add(ll x, ll y, ll w)//用链的方式存储边,方便记录边的信息
{
edge[++len].to = y;
edge[len].val = w;
edge[len].head = out[x];
out[x] = len;
}
vector<ll> ans;
ll ss(ll now, ll fa)//代表以now节点为根节点的树的叶子节点的数量
{
ll cnt = 0, son = 0;
for (ll i = out[now]; i; i = edge[i].head)
{
ll next = edge[i].to;
if (next == fa) continue;
son++;
ans.emplace_back(i);
edge[i].times = ss(next, now);//这条边的出现次数等于以其下端点为根节点的树包含叶子节点的个数
cnt += edge[i].times;
}
if (!son) return 1;//统计叶子节点
return cnt;
}
struct node
{
ll x;
bool operator<(const node &b) const { return edge[b.x].times * (edge[b.x].val - edge[b.x].val / 2) > edge[x].times * (edge[x].val - edge[x].val / 2); }
//每条边的贡献是 出现次数*边权 而为了尽可能的小,我们要按 操作能减去多少贡献 的大小排序
};
int main()
{
ios::sync_with_stdio(false);
ll t;
cin >> t;
while (t--)
{
ll n, S;
cin >> n >> S;
for (ll i = 1; i < n; i++)
{
ll x, y, w;
cin >> x >> y >> w;
add(x, y, w);
add(y, x, w);
}
ss(1, 1);
priority_queue<node> q;
ll sum = 0;
for (auto i : ans)
{
q.push({i});
sum += edge[i].val * edge[i].times;
}
ll op = 0;
while (sum > S)
{
op++;
ll now = q.top().x;
sum -= edge[now].times * (edge[now].val - edge[now].val / 2);
edge[now].val /= 2;
q.pop();
q.push({now});//pq无法自更新,必须要出队入队来更新
}
cout << op << endl;
memset(out, 0, sizeof out);
ans.clear();
len = 0;
}
return 0;
}

浙公网安备 33010602011771号