题目:https://vjudge.net/contest/325352#problem/A
题意:给你一棵树,每个点给一个区间,可以选区间里面任何一个数,然后问怎么安排得到最大边两点之间的差值和,求这个最大差值和
思路:首先可以想到每个点肯定是选择区间端点值,也就是说每个点实际上只有两个值可以选,但是我们安排当前值求出最大边差值不一定最优,这个时候我们可以设立一个数组dp[n][2],代表选当前点的L能得到的最大值和当前选R能得到的最大值,这样最后递归到根节点1就能求出最大值是多少
#include<bits/stdc++.h> #define maxn 100005 #define mod 1000000007 using namespace std; typedef long long ll; struct sss{ ll l,r; }a[maxn]; int t,n; vector<int> mp[maxn]; ll dp[maxn][2]; void dfs(int x,int f){ for(int i=0;i<mp[x].size();i++){ int v=mp[x][i]; if(v==f) continue; dfs(v,x); dp[x][0]+=max(abs(a[x].l-a[v].l)+dp[v][0],abs(a[x].l-a[v].r)+dp[v][1]);//所有子树的差值和 dp[x][1]+=max(abs(a[x].r-a[v].l)+dp[v][0],abs(a[x].r-a[v].r)+dp[v][1]); } } int main(){ scanf("%d",&t); while(t--){ scanf("%d",&n); for(int i=1;i<=n;i++){ mp[i].clear(); } memset(dp,0,sizeof(dp)); int x,y; for(int i=0;i<n-1;i++){ scanf("%d%d",&x,&y); mp[x].push_back(y); mp[y].push_back(x); } for(int i=1;i<=n;i++){ scanf("%d%d",&a[i].l,&a[i].r); } dfs(1,-1); printf("%lld ",max(dp[1][0],dp[1][1])); } }