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
#define fi first
#define se second
#define pb push_back
#define LL long long
#define PII pair 
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;
}

 

你可能感兴趣的:(补题,Codeforces比赛题解,题解)