题意:
n n n个城市由 n − 1 n-1 n−1条路径构成一棵树。总共有 m m m人住在这些城市,第 i i i个城市住的人数是 p i p_i pi。每个人有一个心情,可能为好心情,可能为坏心情。所有人带着一种心情从城市 1 1 1(根节点)出发,出发时可能为好心情,可能为坏心情。在路径上(边)可以改变心情,但只能由好变坏,不能由坏变好。在城市里(点)不会改变心情。现在问,是否存在一种方案,使得经过城市 i i i的好心情的人数-经过城市 i i i的坏心情的人数= h i h_i hi。
题解:
设经过城市 i i i的好心情的人数为 g o o d i good_i goodi,坏心情的人数为 b a d i bad_i badi。已知经过城市 i i i的总人数为
s u m i = p i + ∑ j 为 i 儿 子 s u m j sum_i=p_i+\sum_{j为i儿子}^{}sum_j sumi=pi+j为i儿子∑sumj
可以得到两个式子
s u m i = g o o d i + b a d i sum_i=good_i+bad_i sumi=goodi+badi
h i = g o o d i − b a d i h_i=good_i-bad_i hi=goodi−badi
由此可得
g o o d i = ( s u m i + h i ) / 2 good_i=(sum_i+h_i)/2 goodi=(sumi+hi)/2
b a d i = s u m i − g o o d i bad_i=sum_i-good_i badi=sumi−goodi
那么哪些情况是不合理的呢?
g o o d i < 0 , b a d i < 0 , g o o d i − b a d i ≠ h i good_i<0,bad_i<0,good_i-bad_i\neq h_i goodi<0,badi<0,goodi−badi=hi
(当 ( s u m i + h i ) (sum_i+h_i) (sumi+hi)为奇数的时候,当然是不合理的,为了好看,我们将这个判断转化成了最后的不等式)
那是不是这样就好了呢?当然不是。路过城市 i i i的人中,因为坏心情只能还是坏心情,所以经过城市 i i i中好心情的人数,应该至少满足 i i i所有儿子的好心情的人数。
g o o d i ≥ ∑ j 为 i 的 儿 子 g o o d j good_i\geq \sum_{j为i的儿子}^{} good_j goodi≥j为i的儿子∑goodj
分析完之后,一遍 dfs 就解决了这个问题。
AC代码:
#include <bits/stdc++.h>
#define pb push_back
#define fir first
#define sec second
#define ms(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define sp system("pause")
#define multi int t;cin>>t;while(t--)
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e5+5;
const int mod=10007;
const db pi=acos(-1.0);
vector<int>tr[N];
int p[N],h[N],good[N],bad[N],sum[N];
bool dfs(int u,int fa)
{
sum[u]=p[u];
int g=0;
for(int v:tr[u]){
if(v==fa) continue;
if(dfs(v,u)){
sum[u]+=sum[v];
g+=good[v];
}else return 0;
}
good[u]=(sum[u]+h[u])/2;
bad[u]=sum[u]-good[u];
if(good[u]<g||bad[u]<0||good[u]-bad[u]!=h[u]) return 0;
else return 1;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("D:\\work\\data.in","r",stdin);
#endif
multi{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
tr[i].clear();
good[i]=bad[i]=sum[i]=0;
cin>>p[i];
}
for(int i=1;i<=n;i++) cin>>h[i];
for(int i=1,x,y;i<n;i++){
cin>>x>>y;
tr[x].pb(y);
tr[y].pb(x);
}
if(dfs(1,-1)) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}