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;
}

  

posted @ 2020-07-31 15:38  coastal_taipan  阅读(206)  评论(0编辑  收藏  举报