C. Uncle Bogdan and Country Happiness( 树型递推(其实不能叫dp吧?) )

每个人从1节点走回自己家

一定是前一段路的心情好(可能前一段路长为0),后一段路心情差

我们的难点在哪里?

在于有很多个人,我们不能确定每个人在哪个节点心情开始变差的

但其实我们是可以大概确定的

. \color{Red}Ⅰ.考虑叶子节点

w 对于一个叶子节点w来说

w w , x , y 能到达w的都是家在w的,设这些人到达时有x个人心情好,y个人心情产

{ x + y = p w x y = h w \left\{ \begin{aligned} x+y=p_w \\ x-y=h_w \\ \end{aligned} \right.

x ( p w + h w ) / 2 ,   y p w x 所以x是(p_w+h_w)/2,\ y是p_w-x

( p w + h w ) 其中(p_w+h_w)应该是偶数


. k \color{Red}Ⅱ.考虑非叶子节点k

这一步其实就是由叶子节点往上推的

k , d p [ k ] [ 1 ] k的最少开心人数是所有子节点开心人数相加,记作dp[k][1]

k + p k , d p [ k ] [ 2 ] k的最大不开心人数是所有子节点不开心人数和+p_k,记作dp[k][2]

p k . . . . . . p k k , , . . . 至于为啥加p_k......因为这p_k个人在k节点可能开心,也可能不开心,若都不开心那么人数就最大嘛...

s u m n = d p [ k ] [ 1 ] + d p [ k ] [ 2 ] 那么当前经过这个点的人是sumn=dp[k][1]+dp[k][2]

s u m n , k x , y 由Ⅰ知sumn必须是偶数,那么可以解得k节点有x人心情好,y人心情差

x = ( s u m n + h k ) / 2 , y = s u m n x 这样我们解得x=(sumn+h_k)/2,y=sumn-x

我再重申一下 d p [ k ] [ 1 ] dp[k][1] 是最少开心得人数

因为子节点开心得人在上一个节点一定开心 (只能由开心->不开心)

k , 但是可能还存在一些人在k节点开心,但是跑到子节点就不开心了

x > = d p [ k ] [ 1 ] 所以这里应该满足x>=dp[k][1]

, k , , 判断完之后,由于k点的开心,不开心人数被计算出来了,那么

d p [ k ] [ 1 ] = x , d p [ k ] [ 2 ] = y , dp[k][1]=x,dp[k][2]=y,然后继续向上推


w w > a b s ( h w ) , 然后对任意一个节点w满足经过w的总人数>abs(h_w),比较显然

? d f s ! ! \color{green}然后?然后就开始dfs啊!!

觉得我讲的不好可以在评论区骂我

觉得我讲的好可以在评论区夸我

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2e5+10;
int n,t,dp[maxn][3],flag,h[maxn],p[maxn],m;
vector<int>vec[maxn];
void dfs(int u,int fa)
{
	if( vec[u].size()==1&&u!=1 )//到达叶子节点 
	{
		if( p[u]<abs(h[u]) )	flag=0;
		if( ( h[u]+p[u] )%2==1 )	flag=0;
		dp[u][1]=( h[u]+p[u] )/2;//开心的人数 x
		dp[u][2]=p[u]-dp[u][1];//不开心的人数y
		return;
	}
	for(int i=0;i<vec[u].size();i++)
	{
		int v=vec[u][i];
		if( v==fa )	continue;
		dfs(v,u);
		dp[u][1]+=dp[v][1];//开心的人数至少有这么多 
		dp[u][2]+=dp[v][2];//不开心的人数 
	}
	dp[u][2]+=p[u];
	//dp[u][1]+dp[u][2]是总人数
	int sumn=dp[u][1]+dp[u][2];
	int x=( sumn+h[u] )/2;//该层应该开心的人数 
	int y=( sumn-x );//该层不开心的人数 
	if( sumn<abs(h[u]) )	flag=0;
	if( (sumn+h[u])%2==1 )	flag=0;
	if( x<dp[u][1] )	flag=0; 
	dp[u][1]=x,dp[u][2]=y;
}
signed main()
{
	cin >> t;
	while( t-- )
	{
		flag=1;
		cin >> n >> m ;
		for(int i=1;i<=n;i++)	scanf("%lld",&p[i]);
		for(int i=1;i<=n;i++)	scanf("%lld",&h[i]);
		for(int i=1;i<n;i++)
		{
			int l,r;
			scanf("%lld%lld",&l,&r);
			vec[l].push_back(r);
			vec[r].push_back(l);
		}
		dfs(1,0);
		if( flag )	cout << "YES\n";
		else	cout << "NO\n";
		for(int i=1;i<=n;i++)
		{
			dp[i][1]=dp[i][2]=0;
			vec[i].clear();
		}
	}
}

一起加油努力啊~

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/107705164