题目笔记——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;
}
posted @ 2026-10-27 16:28  show__code  阅读(2)  评论(0)    收藏  举报