每个人从1节点走回自己家
一定是前一段路的心情好(可能前一段路长为0),后一段路心情差
我们的难点在哪里?
在于有很多个人,我们不能确定每个人在哪个节点心情开始变差的
但其实我们是可以大概确定的
Ⅰ . 考 虑 叶 子 节 点 \color{Red}Ⅰ.考虑叶子节点 Ⅰ.考虑叶子节点
对 于 一 个 叶 子 节 点 w 来 说 对于一个叶子节点w来说 对于一个叶子节点w来说
能 到 达 w 的 都 是 家 在 w 的 , 设 这 些 人 到 达 时 有 x 个 人 心 情 好 , y 个 人 心 情 产 能到达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+y=pwx−y=hw
所 以 x 是 ( p w + h w ) / 2 , y 是 p w − x 所以x是(p_w+h_w)/2,\ y是p_w-x 所以x是(pw+hw)/2, y是pw−x
其 中 ( p w + h w ) 应 该 是 偶 数 其中(p_w+h_w)应该是偶数 其中(pw+hw)应该是偶数
Ⅱ . 考 虑 非 叶 子 节 点 k \color{Red}Ⅱ.考虑非叶子节点k Ⅱ.考虑非叶子节点k
这一步其实就是由叶子节点往上推的
k 的 最 少 开 心 人 数 是 所 有 子 节 点 开 心 人 数 相 加 , 记 作 d p [ k ] [ 1 ] k的最少开心人数是所有子节点开心人数相加,记作dp[k][1] k的最少开心人数是所有子节点开心人数相加,记作dp[k][1]
k 的 最 大 不 开 心 人 数 是 所 有 子 节 点 不 开 心 人 数 和 + p k , 记 作 d p [ k ] [ 2 ] k的最大不开心人数是所有子节点不开心人数和+p_k,记作dp[k][2] k的最大不开心人数是所有子节点不开心人数和+pk,记作dp[k][2]
至 于 为 啥 加 p k . . . . . . 因 为 这 p k 个 人 在 k 节 点 可 能 开 心 , 也 可 能 不 开 心 , 若 都 不 开 心 那 么 人 数 就 最 大 嘛 . . . 至于为啥加p_k......因为这p_k个人在k节点可能开心,也可能不开心,若都不开心那么人数就最大嘛... 至于为啥加pk......因为这pk个人在k节点可能开心,也可能不开心,若都不开心那么人数就最大嘛...
那 么 当 前 经 过 这 个 点 的 人 是 s u m n = d p [ k ] [ 1 ] + d p [ k ] [ 2 ] 那么当前经过这个点的人是sumn=dp[k][1]+dp[k][2] 那么当前经过这个点的人是sumn=dp[k][1]+dp[k][2]
由 Ⅰ 知 s u m n 必 须 是 偶 数 , 那 么 可 以 解 得 k 节 点 有 x 人 心 情 好 , y 人 心 情 差 由Ⅰ知sumn必须是偶数,那么可以解得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 这样我们解得x=(sumn+hk)/2,y=sumn−x
我再重申一下 d p [ k ] [ 1 ] dp[k][1] dp[k][1]是最少开心得人数
因 为 子 节 点 开 心 得 人 在 上 一 个 节 点 一 定 开 心 因为子节点开心得人在上一个节点一定开心 因为子节点开心得人在上一个节点一定开心(只能由开心->不开心)
但 是 可 能 还 存 在 一 些 人 在 k 节 点 开 心 , 但 是 跑 到 子 节 点 就 不 开 心 了 但是可能还存在一些人在k节点开心,但是跑到子节点就不开心了 但是可能还存在一些人在k节点开心,但是跑到子节点就不开心了
所 以 这 里 应 该 满 足 x > = d p [ k ] [ 1 ] 所以这里应该满足x>=dp[k][1] 所以这里应该满足x>=dp[k][1]
判 断 完 之 后 , 由 于 k 点 的 开 心 , 不 开 心 人 数 被 计 算 出 来 了 , 那 么 判断完之后,由于k点的开心,不开心人数被计算出来了,那么 判断完之后,由于k点的开心,不开心人数被计算出来了,那么
d p [ k ] [ 1 ] = x , d p [ k ] [ 2 ] = y , 然 后 继 续 向 上 推 dp[k][1]=x,dp[k][2]=y,然后继续向上推 dp[k][1]=x,dp[k][2]=y,然后继续向上推
然 后 对 任 意 一 个 节 点 w 满 足 经 过 w 的 总 人 数 > a b s ( h w ) , 比 较 显 然 然后对任意一个节点w满足经过w的总人数>abs(h_w),比较显然 然后对任意一个节点w满足经过w的总人数>abs(hw),比较显然
然 后 ? 然 后 就 开 始 d f s 啊 ! ! \color{green}然后?然后就开始dfs啊!! 然后?然后就开始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();
}
}
}
一起加油努力啊~