[ABC409E] Pair Annihilation

题目翻译

给你一棵有 \(N\) 个顶点的树。边 \(j\) 权重为 \(w_j\)。另外,顶点 \(i\) 的权重为整数 \(x_i\)。如果是 \(x_i > 0\),那么 \(x_i\) 个正电子被置于顶点 \(i\)。如果是 \(x_i < 0\),那么 \(-x_i\) 个电子被置于顶点 \(i\)

沿着边 \(j\) 移动一个粒子会耗费能量 \(w_j\) 。此外,当一个正电子和一个电子位于同一个顶点时,它们会以相等的数量相互湮灭。

求湮灭所有正电子和电子所需的最小能量。

题目思路

定义 \(sz_i\) 为以节点 \(i\) 为根的树的剩余的粒子数量。负数为有 \(sz_i\) 个电子,反之为有 \(sz_i\) 个正电子。

从节点 \(1\) 开始 DFS。到当前节点 \(u\),遍历每一棵子树。如果子树还有粒子没有湮灭,就要从节点 \(u\) 拿一些粒子给子树,记录消耗。由于每条边的边权都为非负数,所以不存在从其他子树拿粒子会更优的情况。

最后输出即可。

AC Code

#include<bits/stdc++.h>
#define int long long
#define fo(i,a,b)	for(int i=a;i<=b;i++)
using namespace std;
const int N=1e5+5;
int n,ans,a[N],sz[N];
struct node{
	int v,w;
};
vector<node>g[N];
void dfs(int u,int fat){
	sz[u]=a[u];
	for(auto tmp:g[u]){
		int v=tmp.v,w=tmp.w;
		if(v==fat)	continue;
		dfs(v,u);
		sz[u]+=sz[v];
		ans+=w*abs(sz[v]);
	}
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0);
	cin>>n;
	fo(i,1,n)	cin>>a[i];
	for(int i=1,u,v,w;i<n;i++){
		cin>>u>>v>>w;
		g[u].push_back({v,w});
		g[v].push_back({u,w});
	}
	dfs(1,-1);
	cout<<ans;
	return 0;
}
posted @ 2025-06-09 14:46  深申  阅读(20)  评论(0)    收藏  举报