【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;
}