hdu 6725

题目

考虑树形dp,好像以前做过类似的cf题,贪心一下,选取两边的边界能使得答案最大,所以设f[i][j]为第i个结点取左边界还是右边界,转移的时候枚举两个边界就可以了

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<list>
#include<cmath>
#define int long long
using namespace std;
int t,n,l[100005],r[100005],f[100005][2];//0 l,1 r;
bool vis[100005];
list<int>lis[100005];
void dfs(int rt)
{
	vis[rt]=true;
	for(list<int>::iterator it=lis[rt].begin();it!=lis[rt].end();it++)
	{
		if(!vis[*it])
		{
			dfs(*it);
			f[rt][0]+=max(f[*it][0]+abs(l[rt]-l[*it]),f[*it][1]+abs(l[rt]-r[*it]));
			f[rt][1]+=max(f[*it][0]+abs(r[rt]-l[*it]),f[*it][1]+abs(r[rt]-r[*it]));
		}
	}
}
signed main()
{
	cin>>t;
	while(t--)
	{
		memset(f,0,sizeof(f));
		memset(vis,false,sizeof(vis));
		scanf("%lld",&n);
		for(int i=1;i<=n+2;i++)
		{
			lis[i].clear();
		}
		for(int i=1;i<=n-1;i++)
		{
			int u,v;
			scanf("%lld %lld",&u,&v);
			lis[u].push_back(v);
			lis[v].push_back(u);
		}
		//lis[n].clear();
		for(int i=1;i<=n;i++)
		{
			//lis[i].clear();
			scanf("%lld %lld",&l[i],&r[i]);
		}
		dfs(1);
		//int ans=0;
		/*for(int i=1;i<=n;i++)
		{
			ans+=f[i];
		}*/
		printf("%lld\n",max(f[1][0],f[1][1]));
	}
}

猜你喜欢

转载自blog.csdn.net/qq_37073764/article/details/107413719