cf1388C---dfs
题目链接: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;
}

浙公网安备 33010602011771号