[??记录]AT2304 [AGC010C] Cleaning
command_block · · 个人记录
题意 : 一棵树,第
每次可以选择两个不同的叶节点(度数为
判定能不能取完所有石头。
-
\dfrac{s_u-f_u}{2}\leq s_u-\max\limits_{u\rightarrow v}f_v) 这个套路和 [DS记录]P4338 [ZJOI2018]历史 一致。
当
若满足上述条件,不难归纳证明可以构造出合法方案。
复杂度
#include<algorithm>
#include<cstdio>
#include<vector>
#define pb push_back
#define ll long long
#define MaxN 100500
using namespace std;
vector<int> g[MaxN];
ll a[MaxN],f[MaxN],c[MaxN];
bool fl;
void dfs(int u,int fa)
{
if (g[u].size()==1){
c[u]=f[u]=a[u];
return ;
}
ll s=0,mx=0;
for (int i=0,v;i<g[u].size();i++)
if ((v=g[u][i])!=fa){
dfs(v,u);
s+=f[v];
c[u]+=c[v];
mx=max(mx,c[v]);
}
f[u]=2*a[u]-s;
if (f[u]<0||s<0||f[u]>c[u]||(s-f[u])/2>min(c[u]/2,c[u]-mx))fl=0;
if (!fa&&f[u]>0)fl=0;
}
int n;
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)scanf("%lld",&a[i]);
for (int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);
g[u].pb(v);g[v].pb(u);
}
if (n==2){
puts(a[1]==a[2] ? "YES" : "NO");
return 0;
}
int rt=0;
for (int i=1;i<=n;i++)
if (g[i].size()>1)rt=i;
fl=1;dfs(rt,0);
puts(fl ? "YES" : "NO");
return 0;
}