• CodeForces


    http://codeforces.com/problemset/problem/274/B

    题目大意:
     给定你一颗树,每个点上有权值。
     现在你每次取出这颗树的一颗子树(即点集和边集均是原图的子集的连通图)且这颗树中必须包含节点1
     然后将这颗子树中的所有点的点权+1或-1
     求把所有点权全部变为0的最小次数(n<=10^5)

    题解:

      

    因为每一次的子树中都必须有1,所以我们得知每一次变换的话1的权值都会变化

    所以我们以1为根

    现在,我们发现,如果一个节点的权值发生变化,那么他的父节点的权值一定发生变化

    而一个点因为其子节点而导致的,不是用于平衡自己权值的变化是不可避免的

    所以我们考虑最小化这个值,我们假设现在他的所有儿子都是叶子节点

    那么节点u被变化的值即为inc[u] + dec[u]其中inc[u] = max{inc[v]},dec[u] = max{dec[v]}

    inc[u]表示这个节点在最优情况下被加了多少次

    dec[u]表示这个节点在最坏情况下被减了多少次

    所以我们知道,在我们处理完了u的所有子树的问题后,就要解决自己本身的问题

    所以这是根据val[u]的正负来调整inc,和dec

    O(n)dfs即可

    code

      

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 typedef long long ll;
     6 template<typename T>inline void read(T &x){
     7     x=0;char ch;bool flag = false;
     8     while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
     9     while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    10 }
    11 template<typename T>inline T cat_max(const T &a,const T &b){return a>b ? a:b;}
    12 template<typename T>inline T cat_min(const T &a,const T &b){return a<b ? a:b;}
    13 const int maxn = 100010;
    14 struct Node{
    15     int to,next;
    16 }G[maxn<<1];
    17 int head[maxn],cnt;
    18 void add(int u,int v){
    19     G[++cnt].to = v;
    20     G[cnt].next = head[u];
    21     head[u] = cnt;
    22 }
    23 ll val[maxn],inc[maxn],dec[maxn];
    24 int fa[maxn];
    25 #define v G[i].to
    26 void dfs(int u){
    27     for(int i = head[u];i;i=G[i].next){
    28         if(v == fa[u]) continue;
    29         fa[v] = u;
    30         dfs(v);
    31         inc[u] = cat_max(inc[u],inc[v]);
    32         dec[u] = cat_max(dec[u],dec[v]);
    33     }
    34     val[u] = val[u] + inc[u] - dec[u];
    35     if(val[u] <= 0) inc[u] += -val[u];
    36     else dec[u] += val[u];
    37     return;
    38 }
    39 #undef v
    40 int main(){
    41     int n;read(n);
    42     for(int i=1,u,v;i<n;++i){
    43         read(u);read(v);
    44         add(u,v);add(v,u);
    45     }for(int i=1;i<=n;++i) read(val[i]);
    46     dfs(1);
    47     printf("%lld
    ",inc[1]+dec[1]);
    48     getchar();getchar();
    49     return 0;
    50 }
    51   
  • 相关阅读:
    第九篇 正则表达式
    第八篇、递归、装饰器
    第四篇、函数和递归
    第二篇、HTML
    nginx rewrite标签配置以及用户认证配置
    nginx location
    nginx日志配置,以及日志轮询
    nginx别名配置,状态配置,include优化
    第一篇 先用socket模拟web服务器
    第二十八篇、自定义线程池
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6259048.html
Copyright © 2020-2023  润新知