Codeforces Round #660 (Div. 2) Uncle Bogdan and Country Happiness dfs
题目链接:Uncle Bogdan and Country Happiness
题意:
t组输入,每组数据输入如下
首先一个n代表有n个城市,所有城市总人数为m,后面输入pi表示第i个城市的居住人数,后面的hi表示经过这个城市的人中 开心的人数-伤心的人数
后面输入n-1条无向边,每条边的长度都一样
这个图的结构是树形结构,且刚开始所有人都在1点,也就是根节点。他们会走最短路径去回到他们居住的城市
所有人在走的路上都可能由好心情变成坏心情,但是坏心情不会变成好心情,且在城市内这个变化不会发生
题目让你判断给出的hi是否全部正确,是就输出YES
题解:
因为我们不知道经过某个城市的总人数,所以我们需要从树的根节点开始dfs,伤心人数用bad来表示,开心人数用good来表示,totali表示经过i点的总人数
我们得到两个方程式
good+bad=totali
good-bad=hi
这样我们可以求出来good和bad,但是我们还需要去判断这个good正确不正确,因为所有人在路上都可能由好心情变成坏心情,所以说越靠近根节点,那么good的数量肯定会更大,所以我们统计一下子节点算出来的good的和ans,用ans和此节点算出来的good作比较,如果ans>good那就肯定不行
还要判断一下abs(hi)<=total
代码:
#include<stack> #include<queue> #include<map> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #define fi first #define se second using namespace std; typedef long long ll; const int maxn=1e5+10; const int mod=1e9+7; const double eps=1e-8; ll p[maxn],h[maxn],flag,total[maxn],good[maxn]; vector<ll>w[maxn]; void add_edge(ll x,ll y) { w[x].push_back(y); w[y].push_back(x); } void dfs(ll x,ll fx) { ll len=w[x].size(),sum=0; total[x]=p[x]; for(ll i=0;i<len;++i) { ll y=w[x][i]; if(y==fx) continue; dfs(y,x); total[x]+=p[y]; sum+=good[y]; if(flag) return; } p[x]=total[x]; if(flag) return; //if(total[x]==0) return; 之前认为total等于0就不需要判断,没想不行 //因为题目让你判断hi的值是否全部正确,就算total等于0,我们也需要去判断。。。 if(abs(h[x])>total[x]) { flag=1; return; } if((h[x]+total[x])%2==0 && ((h[x]+total[x])/2)>=h[x]) { //printf("%d******%d\n",x,total[x]); good[x]=(h[x]+total[x])/2; if(good[x]<sum) { flag=1; return; } } else { flag=1; } return; } int main() { ll t; scanf("%lld",&t); while(t--) { ll n,m; flag=0; memset(good,0,sizeof(good)); scanf("%lld%lld",&n,&m); for(ll i=1;i<=n;++i) w[i].clear(); for(ll i=1;i<=n;++i) scanf("%lld",&p[i]); for(ll i=1;i<=n;++i) scanf("%lld",&h[i]); for(ll i=1;i<n;++i) { ll x,y; scanf("%lld%lld",&x,&y); add_edge(x,y); } dfs(1,0); if(flag || total[1]!=m) { printf("NO\n"); } else { printf("YES\n"); } } return 0; }