Codeforces 1388:C. Uncle Bogdan and Country Happiness(bfs+dfs)

(题目链接)
题意:起初所有人都在1号城市,总共有m个人,每个城市有pi个人,每个城市都有一个幸福指数:快乐的人减去不快乐的人。给出n-1条路:u,v,代表城市u和城市v有一条双向边,每个人回到自己的城市是走最短路,也就是不会经过一个节点两遍,每个人在路途中可能变得不快乐,以后的路不能变得快乐,问给出的数据能不能满足每个城市的幸福指数。

思路:树形结构+从某个点出发到达其他所有节点,当然会想到bfs模拟。但是bfs模拟还需要某些信息:某个节点所需要经过的总人数,以及某个节点快乐的人数,这里dfs处理就好了。选择从0开始,避免特判1。很容易推出:当前节点不快乐的人数 = (当前节点所经过的总人数-当前节点的幸福值)/2 , 快乐的人数直接总人数减不快乐的人就好了。还要注意不满足数据构造的情况:1.如果:当前节点所经过的总人数-当前节点的幸福值为奇数,很显然构造不出这个数据。2.如果当前节点所经过的总人数-当前节点的幸福值为负数。3.如果当前快乐的人数为负数,肯定不满足。
(比赛的时候思路清晰的一批,要干嘛要写啥。结果写的时候这里有bug,那里有bug,情况讨论也是表述不清。写代码用了一个多小时,第二天早上才写出。吐了,还是码力不足。果然是自己太菜=.=,)
代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<stack>
#include<set>
using namespace std;
#define pb push_back
#define POP pop_back()
#define ll long long
#define db double
#define POP pop_back()
#define endl '\n'
const int maxn = 1e5+5;
const int inf = 0x3f3f3f3f;
const ll inF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const db eps = 1e-8;
ll a[maxn] , sum[maxn] , b[maxn] , h[maxn] , m;
int t , n;
bool vis[maxn] , ok;
vector<int>ve[maxn];
ll dfs(int x , int fa){
	int len = ve[x].size();
	sum[x] = a[x];
	for(int i = 0;i < len;i++){
		if(ve[x][i] == fa)continue;
		sum[x] += dfs(ve[x][i] , x);//当前节点所经过的总人数
	}
	h[x] = sum[x]-(sum[x]-b[x])/2;//求出当前节点所需的快乐人数
	/*数据有几点不满足的情况:
	如果不快乐的人数是负数。
	如果快乐的人是负数。
	如果sum[x] - b[x] 不为偶数,显然不可能构造这个幸福值。
	*/
	if((sum[x]-b[x])%2 != 0 || sum[x]-b[x] < 0 || h[x] < 0)ok = 0;
	return sum[x];
}
struct node{
	int id;
	ll cnt;
};
int main(){
	cin >> t;
	ve[0].pb(1);
	while(t--){
		scanf("%d%lld",&n,&m);
		sum[0] = 0;
		for(int i = 1;i <= n;i++){
			scanf("%lld",a+i);
			ve[i].clear();
			sum[i] = 0;
			vis[i] = 0;
		}
		b[0] = m;
		for(int i = 1;i <= n;i++)scanf("%lld",b+i);
		int u , v;
		for(int i = 1;i < n;i++){
			scanf("%d%d",&u,&v);
			ve[u].pb(v);
			ve[v].pb(u);
		}
		ok = 1;
		dfs(0,0);
		queue<node>q;
		q.push((node){0,m});//从0开始可以不用特判1
		if(m < h[1])ok = 0;
		node now;
		int len , to , cnt , cct;
		vis[0] = 1;
		while(!q.empty()){
			now = q.front() , q.pop();
			len = ve[now.id].size();
			for(int i = 0;i < len;i++){
				to = ve[now.id][i];
				if(!vis[to]){
					vis[to] = 1;
					if(sum[to] > 0){
//如果这个节点所需的快乐人数大于剩下的快乐人数那就无法构造这个节点的数据。
						if(h[to] > now.cnt)ok = 0;
//贪心一下,流经这个节点时候,只需要这个节点所需要的快乐人数,尽量让快乐的人走其他的分支。						
						q.push((node){to,h[to]});
						now.cnt -= h[to];
					}
				}
			}
		}
		puts(ok?"YES":"NO");
	}
	return 0;
}

你可能感兴趣的:(刷题记录,dfs,bfs)