Codeforces Round #660 (Div. 2)C-Uncle Bogdan and Country Happiness(dfs+思维)

题目链接


题目大意:
给一个有N个结点的树,每个结点上都会有相应数量的工人居住,每天早上所有的工人都在根节点1,到了晚上,所有的工人都要一起回家,每个结点都有个快乐检查器,快乐值=快乐的人数-不快乐的人数,心情只能由快乐变为不快乐,再给N-1个快乐值h[i],问能否满足。
解题思路:
先假设当前结点开心的人数为good,不开心的人数为bad,所以可得式子good+bad=总人数,good-bad=h[i],联立两式可得2*good=(总人数+h[i]),所以总人数+h[i]必须是偶数,同时good必须小于总人数,good[u]>good[v](v为u的子节点),因为结构为树,所以要把u的子节点的good相加在与u比较。
代码:
// #include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#define pb emplace_back
#define LOCAL
  
using namespace std;
  
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
const int maxn = 1e5+5;
typedef long long ll;
typedef pair<int,int> Pii;
 
template <typename T>inline void read(T& t){
    char c=getchar();t=0;
    int f=1;
    while(!isdigit(c)){
       if(c=='-')f=-1;
        c=getchar();
    }
    while(isdigit(c))t=t*10+c-48,c=getchar();
    t=f*t;
}
  
template <typename T,typename... Args> inline void read(T& t,Args&... args){
    read(t);read(args...);
}

int n,m;
bool flag;
int p[maxn],h[maxn];
vector<int> e[maxn];

void init(){
    for(int i=1;i<=n;i++){
        p[i]=0;
        h[i]=0;
        e[i].clear();
    }
}

void dfs(int x,int fa){
    int sum=0;
    for(auto it:e[x]){
        if(it==fa)continue;
        dfs(it,x);
        p[x]+=p[it];
        sum+=h[it];
    }
    h[x]+=p[x];//总人数
    if((h[x]%2)||(h[x]>2*p[x])||(h[x]<sum)){1.总人数必须为偶数,2.good人数必须小于总人数,3.good必须小于父节点
        flag=false;
    }
}
 
int main(){
    int t;
    read(t);
    while(t--){
        init();
        flag=true;
        read(n,m);
        for(int i=1;i<=n;i++){
            read(p[i]);
        }
        for(int i=1;i<=n;i++){
            read(h[i]);
        }
        for(int i=1;i<n;i++){
            int u,v;
            read(u,v);
            e[u].emplace_back(v);
            e[v].emplace_back(u);
        }
        dfs(1,0);
        puts(flag?"YES":"NO");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值