题目
题目链接:https://codeforces.com/contest/1324/problem/F
思路
把树都看成一块一块的~
先用第一个dfs跑出这个数所在的这一块最多由多少个,每一个的值由他周围的的最大值决定的,这部相当于预处理最大值,用val存最大值。
在用一个dfs跑一下这个数和相邻的看看可不可以再多,用ans存结果。
最开始要先处理一下输入,把输入的0变成-1方便计算
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<ctime>
#include<iostream>
#include<string>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<iomanip>
#include<list>
#include<bitset>
#include<sstream>
#include<fstream>
#include<complex>
#include<algorithm>
#if __cplusplus >= 201103L
#include <unordered_map>
#include <unordered_set>
#endif
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
struct sut{
int to,next;
}edge[800010];
int head[200010],val[200010],ans[200010],tot=0,a[200010];
void add_edge(int u,int v){
edge[++tot].to=v;
edge[tot].next=head[u];
head[u]=tot;
}
void dfs1(int f,int s){
// cout<<s<<endl;
val[s]=a[s];
for(int i=head[s];i;i=edge[i].next){
int v1=edge[i].to;
if(v1==f) continue;//节点相同就不跑
dfs1(s,v1);
if(val[v1]>=0)val[s]+=val[v1];
//cout<<val[s]<<" "<<s<<endl;
}
}
void dfs2(int f,int s){
ans[s]=val[s];
if(val[s]>0) ans[f]-=ans[s];
if(ans[f]>0) ans[s]+=ans[f];
for(int i=head[s];i;i=edge[i].next){
int v1=edge[i].to;
if(v1==f) continue;
dfs2(s,v1);
}
if(val[s]>0) ans[f]+=val[s];
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int n,t;
cin>>n;
t=n;
for(int i=1;i<=n;i++) {
cin>>a[i];
if(a[i]==0) a[i]=-1;}
n--;
memset(head,0,sizeof head);
while(n--){
int u,v;
cin>>u>>v;
add_edge(u,v);
add_edge(v,u);
}
dfs1(0,1);
// for(int i=1;i<=n;i++) cout<<<<i<<endl;
dfs2(0,1);
for(int i=1;i<=t;i++) cout<<ans[i]<<" \n"[i==n];
return 0;
}