【图论】AGC010C Cleaning

分析:

以任意一个叶子结点为根,然后对每个点,考虑其会向上贡献多少条路径,顺便统计是否合法。详见代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 100010
typedef long long ll;
using namespace std;
int n;
vector<int> a[MAXN];
ll val[MAXN];
int u,v;
ll dfs(int x,int fa){
	ll sum=0,mx=0;
	if(a[x].size()==1&&fa!=0)
		return val[x];
	for(int i=0;i<int(a[x].size());i++){
		int u=a[x][i];
		if(u==fa)
			continue;
		ll s=dfs(u,x);
		mx=max(mx,s);
		sum+=s;
	}
	if(sum<val[x]||sum>val[x]*2){
		PF("NO");
		exit(0);
	}
	ll nx=2ll*val[x]-sum;
	if((sum-nx)/2ll<mx-nx){
		PF("NO");
		exit(0);	
	}
	return 2ll*val[x]-sum;
}
int main(){
	//freopen("tree.in","r",stdin);
	//freopen("tree.out","w",stdout);
	SF("%d",&n);
	for(int i=1;i<=n;i++)
		SF("%lld",&val[i]);
	for(int i=1;i<n;i++){
		SF("%d%d",&u,&v);	
		a[u].push_back(v);
		a[v].push_back(u);
	}
	int ans=0;
	for(int i=1;i<=n;i++)
		if(a[i].size()==1){
			ans=(dfs(i,0)==val[i]);
			break;
		}
	if(ans==0)
		PF("NO");
	else
		PF("YES");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值