题目笔记——P17511 [入门赛 #52] 月饼调配
考虑每条边的贡献。
对于从父亲节点 \(u\) 到儿子节点 \(v\) 之间的边,所要在这条边上做的贡献就是把 \(v\) 子树中多余的月饼传递给外面的 \(u\),或把外面多余的月饼传递给 \(v\),其实就是这条边的某一边的原本个数与期望个数的差的绝对值,计为 \(cnt\)。
然而题目给出了一个遍一次最多只能运送 \(c_i\) 个,所以我们要把上面求出的 \(cnt\) 个月饼每次运 \(c_i\) 个,就是 \(\lceil \frac{cnt}{x} \rceil\) 次,最后求出每个边的贡献即可。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 20;
struct node{int v, w;};
int n, s[N], t[N], siz[N], wt[N], ans;
vector<node> e[N];
void dfs(int u, int fa){
siz[u] = s[u];
wt[u] = t[u];
for(node v : e[u]){
if(v.v == fa) continue;
dfs(v.v, u);
siz[u] += siz[v.v];
wt[u] += wt[v.v];
}
}
void dfs2(int u, int fa){
for(node v : e[u]){
if(v.v == fa) continue;
ans += (abs(siz[v.v] - wt[v.v]) + v.w - 1) / v.w;
dfs2(v.v, u);
}
}
signed main(){
cin >> n;
for(int i = 1; i <= n; i++) cin >> s[i];
for(int i = 1; i <= n; i++) cin >> t[i];
for(int i = 1, u, v, w; i < n; i++){
cin >> u >> v >> w;
e[u].push_back({v, w});
e[v].push_back({u, w});
}
dfs(1, 0);
dfs2(1, 0);
cout << ans;
return 0;
}

浙公网安备 33010602011771号