• CF1324F Maximum White Subtree(树形dp)


    Maximum White Subtree

    思路:我们假设节点1为root,如果我们知道了root所有子树的最优情况,那么我们可以把1节点的最优情况传递给它的所有子树(当然如果传递给如图2的子树,那么需要把以2为root的最优贡献给减去,再传递root[1]的最优价值)。那我们这么维护子树的最优情况?很显然,如果子树的价值是负数,那么子树给父结点的价值应该是0,如果是正数,则可以把这个价值传递给父结点。

     1 #include <iostream>
     2 #include <deque>
     3 #include <algorithm>
     4 #include <stack>
     5 #include <vector>
     6 #include <cstring>
     7  
     8 using namespace std;
     9  
    10 const int N = 2e5 + 10;
    11  
    12 struct Tree{
    13     int cnt;
    14     bool white;
    15 }tree[N];
    16 struct Edge{
    17     int to, nxt;
    18 }e[N << 1];
    19 int head[N];
    20 int n, tot;
    21  
    22 inline void add(int u, int v){
    23     e[tot].to = v; e[tot].nxt = head[u]; head[u] = tot++;
    24     e[tot].to = u; e[tot].nxt = head[v]; head[v] = tot++;
    25 }
    26  
    27 int process(int now, int pre){
    28     int cnt = 0;
    29     for(int o = head[now]; ~o; o = e[o].nxt){
    30         if(e[o].to != pre){
    31             cnt += process(e[o].to, now);
    32         }
    33     }
    34     tree[now].cnt = tree[now].white ? 1 : -1; //自身是否是白色
    35     tree[now].cnt += cnt > 0 ? cnt : 0; //子树给的价值
    36     return max(tree[now].cnt, 0); //返回最优价值
    37 }
    38  
    39 void push_down(int now, int pre){
    40     for(int o = head[now]; ~o; o = e[o].nxt){
    41         if(e[o].to != pre){
    42             if(tree[now].cnt > 0){ //如果父结点价值为正,则传递价值
    43                 //如果该子树价值为正,则父结点传递的价值减去该子树传递的价值
    44                 //否则直接传递父结点的价值
    45                 if(tree[e[o].to].cnt > 0) tree[e[o].to].cnt += max(tree[now].cnt - tree[e[o].to].cnt, 0);
    46                 else tree[e[o].to].cnt += tree[now].cnt;
    47             }
    48             push_down(e[o].to, now);
    49         }
    50     }
    51 }
    52  
    53 void solve(){
    54  
    55     cin >> n;
    56     for(int i = 1; i <= n; ++i) head[i] = -1; tot = 0;
    57     for(int i = 1; i <= n; ++i){
    58         cin >> tree[i].white;
    59     }
    60     int u, v;
    61     for(int i = 1; i < n; ++i){
    62         cin >> u >> v;
    63         add(u, v);
    64     }
    65     process(1, 0);
    66     push_down(1, 0);
    67     for(int i = 1;i <= n; ++i) cout << tree[i].cnt << " ";
    68     cout << endl;
    69 }
    70  
    71 int main(){
    72     
    73     ios::sync_with_stdio(false);
    74     cin.tie(0);
    75     cout.tie(0);
    76     solve();
    77     
    78     return 0;
    79 }
  • 相关阅读:
    Liunx-----Shell脚本流程控制--顺序、选择、循环
    oracle基本查询
    Shell脚本练习题
    Shell脚本:选择结构、循环结构、
    Shell脚本
    Linux的基本命令
    动态页面技术(JSP/EL/JSTL)
    小功能:访问页面距上次访问有多久时间
    添加验证码,并验证验证码是否正确
    注册,登陆的Servlet、dao、service、domain、jsp页面、
  • 原文地址:https://www.cnblogs.com/SSummerZzz/p/12707022.html
Copyright © 2020-2023  润新知