#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int b[N], p[N];
vector<int>g[N];
ll ans, bas;
int n;
int dfs(int u, int fa) {
vector<int>vec;//储存儿子节点最多可以被合并多少步
for (auto i : g[u]) {
if (i != fa) {
vec.push_back(dfs(i, u));
}
}
ll sum = 0; //储存在不考虑p的情况下,最多能合并所有儿子多少操作
for (auto i : vec) {
sum += min(b[u], i); //合并操作数量不能多于u点本身
}
if (sum >= (ll)b[u]*p[u]) { //如果所有儿子可合并的操作超过u点本身(b[u]*p[u])
ans += (ll)b[u] * p[u]; //只能取u点本身的极限
return 0;//而且不能再被u点的父亲扩展,返回值为0
}
ans += sum; //否者就将所有儿子的合并加到ans
return min((ll)b[u] * p[u] - sum, (ll)b[u]);
}
void slove() {
cin >> n;
ans = bas = 0;
for (int i = 1; i <= n; i++)
g[i].clear();
for (int i = 1; i < n; i++) {
int a, b;
cin >> a >> b;
g[a].push_back(b);
g[b].push_back(a);
}
for (int i = 1; i <= n; i++) {
cin >> b[i] >> p[i];
bas += b[i]; //如果使用暴力,需要多少步
}
dfs(1, 0);
cout << bas - ans << endl; //ans就是可以优化的步数
}
int main() {
ios;
int t;
cin >> t;
while (t--) {
slove();
}
}
2021百度之星复赛03 Subtraction (贪心)
最新推荐文章于 2022-09-20 21:59:50 发布