题目链接:https://codeforces.com/contest/1388/problem/C
题意太长了就不写了
首先统计经过每个点k的人数num[k],注意num[k]和h[k]必须是同奇偶的(第一个判定条件),且h[k]<=num[k]和h[k]+num[k]>0(第二个条件。一开始没写后面那个......)。最后假设在住在k的p[k]个人全都是bad mood的情况下还有Σh[v[k][i]]>p[k]+h[k],则不满足(第三个条件),题解里用g直接把good mood的人数算出来了感觉更清楚。
想想一开始不对的原因:一是比赛时三个条件的细节没完全想清楚;二是直接暴力统计每个点经过的人数tle了,得改成在dfs里统计;三是在vector里只加了单向边于是wa,看来以后写树或者无向图的dfs都用双向边+vis数组吧
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=2e5+10; int t,n,i,j,k,m,f; int p[maxn],h[maxn],num[maxn],vis[maxn]; vector<int> v[maxn]; void dfs(int k){ vis[k]=1; int s=0;num[k]=p[k]; for (int i=0;i<v[k].size();i++) if (vis[v[k][i]]==0){ dfs(v[k][i]); num[k]+=num[v[k][i]]; //统计经过点k的人数 s+=h[v[k][i]]; } if ((num[k]+h[k])%2!=0||h[k]>num[k]||h[k]+num[k]<0) f=1; if (s>h[k]+p[k]) f=1; } int main(){ scanf("%d",&t); while (t--){ scanf("%d%d",&n,&m); for (i=1;i<=n;i++) { v[i].clear();vis[i]=0; } for (i=1;i<=n;i++) scanf("%d",&p[i]); for (i=1;i<=n;i++) scanf("%d",&h[i]); for (i=1;i<=n-1;i++){ int x,y; scanf("%d%d",&x,&y); v[x].push_back(y);v[y].push_back(x); //改成这样就过了...... } f=0;dfs(1); if (f==1) cout<<"NO"<<endl;else cout<<"YES"<<endl; } return 0; }