Diversity
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 27 Accepted Submission(s): 19
Problem Description
给你一棵n个点的树,对于节点i,你要给它标上一个[li,ri]之间的数,要求所有边两端节点上标的数字的差的绝对值的总和最大。
Input
第一行一个整数T(1≤T≤5)表示数据组数。对于每组数据格式如下。
第一行一个正整数 n(2≤n≤105)。
接下来n−1行,每行两个正整数 u,v(1≤u,v≤n),表示一条边。
接下来n行,第i行两个正整数li,ri(1≤li≤ri≤109)。
Output
对于每组数据,一个整数表示答案。
Sample Input
1 5 1 2 2 3 3 4 4 5 1 5 2 7 7 9 5 8 3 4
Sample Output
16
Source
2019 年百度之星·程序设计大赛 - 复赛
Recommend
heyang | We have carefully selected several similar problems for you: 6730 6729 6728 6727 6726
分析:
简单树形DP,从叶子节点到根更新,dp[i][0]表示i节点选择l[i],dp[i][1]表示i节点选择r[i],状态转移即可。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 100010; int n, l[maxn], r[maxn]; ll dp[maxn][2]; vector<int> G[maxn]; void dfs(int u, int fa) { dp[u][0] = dp[u][1] = 0; for(int v : G[u]) if(v != fa) { dfs(v, u); dp[u][0] += max(dp[v][0]+abs(l[v]-l[u]), dp[v][1]+abs(r[v]-l[u])); dp[u][1] += max(dp[v][0]+abs(l[v]-r[u]), dp[v][1]+abs(r[v]-r[u])); } } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i=1; i<=n; i++) G[i].clear(); for(int i = 1; i < n; ++i) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } for(int i=1; i<=n; i++) scanf("%d%d", &l[i], &r[i]); dfs(1, -1); printf("%lld\n", max(dp[1][0], dp[1][1])); } return 0; }