【Codeforces1528A】Parsa's Humongous Tree(树、动态规划)

题目大意:

给定一颗树,每个节点有两个数,为每个节点选择其中一个数,求所有相邻节点所选数之差的绝对值之和。


考虑动态规划。

\(dp_{u,0}\)为节点i选择较小的数,以节点\(u\)为根的子树对答案的贡献的最大值。

\(dp_{u,1}\)为节点i选择较大的数,以节点\(u\)为根的子树对答案的贡献的最大值。

有状态转移方程:

\(dp_{u,0}=\sum max(dp_{v,0}+|l_u-l_v|,dp_{v,1}+|l_u-r_v|)\)

\(dp_{u,1}=\sum max(dp_{v,0}+|r_u-l_v|,dp_{v,1}+|r_u-r_v|)\)

其中\(v\)\(u\)的子节点。

从节点\(1\)开始,对整棵树进行深度优先搜索的同时,计算出\(dp\)数组。

最后的答案为\(max(dp_{1,0},dp_{1,1})\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,l[100000+10],r[100000+10];
ll dp[100000+10][2];
vector<ll> G[100000+10];
void dfs(ll u,ll fa){
	dp[u][0]=dp[u][1]=0;
	for(ll i=0;i<G[u].size();i++){
		ll v=G[u][i];
		if(v==fa)continue;
		dfs(v,u);
		dp[u][0]+=max(dp[v][0]+abs(l[u]-l[v]),dp[v][1]+abs(l[u]-r[v]));
		dp[u][1]+=max(dp[v][0]+abs(r[u]-l[v]),dp[v][1]+abs(r[u]-r[v]));
	}
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	int T;
	cin >> T;
	while(T--){
		cin >> n;
		for(ll i=1;i<=n;i++)cin >> l[i] >> r[i];
		for(ll i=1;i<=n;i++)G[i].clear();
		for(ll i=1;i<=n-1;i++){
			ll u,v;
			cin >> u >> v;
			G[u].push_back(v);
			G[v].push_back(u);
		}
		dfs(1,0);
		cout << max(dp[1][0],dp[1][1]) << endl;
	}
	return 0;
}
posted @ 2023-08-31 16:38  Alric  阅读(7)  评论(0编辑  收藏  举报