专栏文章

AT_abc409_e 题解

题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mip46cme
此快照首次捕获于
2025/12/03 05:52
3 个月前
此快照最后确认于
2025/12/03 05:52
3 个月前
查看原文

题目大意

给定一颗树与其点权、边权,从一个点 uu 移动 11 至其相邻点 vv 代价为边 (u,v)(u,v) 的权值 wu,vw_{u,v},求将所有点权变为 00 的最小代价。

题目分析

首先,显然,从一个点移动 11 至另一个点的最小代价是固定的,为其简单路径的边权总和,则只要不重复走边结果一定是最优的。
其次,我们发现从 uu 移动 11vv 等价与从 vv 移动 1-1uu,则任选一点为根,使用树形动态规划,将所有点权移动到根节点即可。
状态转移方程:fu=fu+fvf_u = f_u + f_v
答案累加:ans=ans+fvwu,vans = ans + \lvert f_v \rvert * w_{u,v}
可以说是板子题了。

Code

CPP
#include<bits/stdc++.h>

using namespace std;

#define ll long long
#define PII pair<int, int>
#define PLL pair<ll, ll>

const ll inf = LONG_LONG_MAX, N = 100050;

ll n, u, v, c, ans = 0; 
ll arr[N]; 
vector<PII> e[N];

void dfs(ll now, ll fa){
	for(PII i : e[now]){
		int y = i.first, w = i.second;
		if(y == fa) continue;
		dfs(y, now);
		ans += w * abs(arr[y]);
		arr[now] += arr[y];
	}
}

int main(){
	scanf("%lld", &n);
	for(int i = 1; i <= n; i ++)
		scanf("%lld", &arr[i]);
	for(int i = 1; i < n; i ++){
		scanf("%lld%lld%lld", &u, &v, &c);
		e[u].push_back({v, c});
		e[v].push_back({u, c});
	}
	dfs(1, -1);
	printf("%lld\n", ans);
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...