Codeforces Round #627 (Div. 3) F

F. Maximum White Subtree

观察题意 发现金典的就是一个全集的意思
显然我们考虑转化成一个图左边+右边这样情况
对于节点u 我们考虑其子树的贡献
显然该点v贡献要是为负数 我们直接不要
否则我们才要
然后我们钦定1为根节点 先自下而上统计每一个节点子树方向的最大贡献
然后我们再自上而下 因为我们节点u只有一个父亲 和一个以自己为根的子树 所以这样显然具有完备性
对于节点u 我们设去的子节点为v
要是a[v]>0 显然我们a[u]里包含a[v]的贡献 所以我们可以将a[v]更新
要是a[v]<=0 显然我们这里没有a[v]的贡献 我们可以将a[v]+上a[u]的贡献
当然因为我们a[v]可能是负数 所以切记都是去更新 不是直接替换
这道题就做完了!

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
const int M = 998244353;
const int mod = 1e9+7;
#define int long long
int up(int a,int b){return a<0?a/b:(a+b-1)/b;}
#define endl '\n'
#define all(x) (x).begin(),(x).end()
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
#define _ 0
#define pi acos(-1)
#define INF 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
vector<int>g[N],a(N);
int n;
void dfs(int u,int fa){
    for(auto v:g[u]){
        if(v==fa)continue;
        dfs(v,u);
        if(a[v]>0)a[u]+=a[v];
    }
}
void bfs(int u,int fa){
    for(auto v:g[u]){
        if(v==fa)continue;
        if(a[v]>0)a[v]=max(a[v],a[u]);
        else a[v]=max(a[v],a[v]+a[u]);
        bfs(v,u);
    }
}
void solve() {
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(!a[i])a[i]=-1;
    }
    for(int i=1;i<n;i++){
        int u,v;cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(1,0);
    bfs(1,0);
    for(int i=1;i<=n;i++)cout<<a[i]<<' ';cout<<endl;
}
signed main(){
    fast
    int t;t=1;//cin>>t;
    while(t--) {
        solve();
    }
    return ~~(0^_^0);
}
posted @ 2022-10-31 00:43  ycllz  阅读(22)  评论(0)    收藏  举报