Codeforces Round #660 (Div. 2)1388C题解

1388C. Uncle Bogdan and Country Happiness

题意:国家有N个城市,1号城市为首都,有M个国民,每个国民都在首都工作,晚上返回家中,给定每个城市有多少国民居住。每个城市都有一个心情检测器,当国民经过城市时,心情检测器根据国民的心情加减1,但是心情检测器并不精确,所以要求你去判断在所有国民回家之后心情检测器上的数值是否正确。

思路:肯定是从叶子结点倒着遍历整颗树,从下往上,每个结点都判断是否合法。对于每个结点记录两个量:一个是经过这个结点的人数会有多少(ei数组),一个是这其中有多少个人是好心情(good数组)。那么good[i] = (h[i] + ei[i])/2,且 ei[i] 和 h[i] 要同奇偶性才可以,那么只要判断这几个变量之间的关系是否合法就能够知道当前结点是否合法:好心情人数必须不小于0,好心情人数不能大于经过这个结点的总人数,好心情人数不能小于这个结点的最小好心情人数(sum),sum 的计算则是当前结点的所有孩子结点的好心情人数之和。

AC代码:

/*---------------------------------
 *File name: A.cpp
 *Creation date: 2020-07-31 10:45
 *Link: 
 *-------------------------------*/
#pragma GCC diagnostic error "-std=c++11"
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define LL long long
#define PII pair<int, int> 
using namespace std;
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const LL mod = 1e9 + 7;

inline int read(){
	char c = getchar();
	while(!isdigit(c)) c = getchar();
	int x = 0;
	while(isdigit(c)){
		x = x * 10 + c - '0';
		c = getchar();
	}
	return x;
}

int p[maxn];
int h[maxn];

struct Edge{
	int v, next;
}edge[maxn << 1];
int tot, head[maxn];
int good[maxn], ei[maxn];//好心情、总人数

inline void Add_Edge(int u, int v){
	edge[tot].v = v;
	edge[tot].next = head[u];
	head[u] = tot++;
}

bool outputjudge = 1;

void Dfs(int u, int f){
	bool flag = 0;
	ei[u] = p[u];
	int sum = 0;
	for(int i = head[u]; i != -1; i = edge[i].next){
		int v = edge[i].v;
		if(v == f) continue;
		flag = 1;
		Dfs(v, u);
		sum += good[v];
		ei[u] += ei[v];
	}
	good[u] = ei[u] + h[u] >> 1;
	//printf("%d : good = %d, ei = %d, sum = %d, h = %d\n", u, good[u], ei[u], sum, h[u]);
	if((ei[u] + h[u]) % 2) outputjudge = 0;//同奇偶性
	if(good[u] < 0) outputjudge = 0;//好心情人数不小于0
	if(good[u] > ei[u]) outputjudge = 0;//好心情人数不大于总人数
	if(good[u] < sum) outputjudge = 0;//好心情人数不小于孩子结点好心情人数和
}

int main(){
	int t = read();
	while(t--){
		int n = read(), m = read();
		outputjudge = 1;
		tot = 0;
		for(int i = 1; i <= n; ++i) head[i] = -1, good[i] = 0;
		for(int i = 1; i <= n; ++i) p[i] = read();
		for(int i = 1; i <= n; ++i) scanf("%d", h + i);
		for(int i = 1; i < n; ++i){
			int u = read(), v = read();
			Add_Edge(u, v);
			Add_Edge(v, u);
		}
		Dfs(1, 0);
		if(outputjudge) printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值