zoukankan      html  css  js  c++  java
  • Codeforces Round #168 (Div. 1) B. Zero Tree 树形dp

    题目链接:

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

    题意:

    给出一棵树,每个点有权值,每次操作可以对一个联通子集中的点全部加1,或者全部减1,且每次操作必须包含点1,问最少通过多少次操作可以让整棵树每个点的权值变为0.

    思路:

    http://blog.csdn.net/qq_24451605/article/details/48622953

    • 定义状态up[u],down[u]代表点u被加操作的次数和点u被减操作的次数
    • 因为必须包含点1,所以我们将树的根定在点1,那么对于每一点的子树中点,如果要修改的话,那么一定会经过当前这个点,因为这是通向根的必经之路。
    • 所以对于每个点u,它被加修改和减修改的次数,就是它的儿子中进行该操作的最大次数,因为如果有两个儿子都需要进行该操作,那么完全可以两步并一步,所以只需要取最大值就可以了。
    • 那么也就是  up[u]=max(up[u],up[v]) v是u的子节点
    • down[u]同理。
    • 因为每次修改一定会修改点1,所以最后答案就是up[1]+down[1] 

    神奇啊,这样的转换 我想不到啊...orz,1这个根节点连接所有的修改,父节点修改的次数是子节点的最大值,这样就把联通子集通过1神奇的联系在一起。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 #define MS(a) memset(a,0,sizeof(a))
     5 #define MP make_pair
     6 #define PB push_back
     7 const int INF = 0x3f3f3f3f;
     8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
     9 inline ll read(){
    10     ll x=0,f=1;char ch=getchar();
    11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 //////////////////////////////////////////////////////////////////////////
    16 const int maxn = 1e5+10;
    17 
    18 vector<int> g[maxn];
    19 int n;
    20 ll a[maxn],up[maxn],down[maxn];
    21 
    22 void dfs(int u,int fa){
    23     for(int i=0; i<(int)g[u].size(); i++){
    24         int v = g[u][i];
    25         if(v == fa) continue;
    26         dfs(v,u);
    27         up[u] = max(up[u],up[v]);
    28         down[u] = max(down[u],down[v]);
    29     }
    30     a[u] = a[u]+up[u]-down[u];
    31     if(a[u] > 0) down[u] += a[u];
    32     else up[u] -= a[u];
    33 }
    34 
    35 int main(){
    36     cin >> n;
    37     for(int i=1; i<n; i++){
    38         int u,v; cin>>u>>v;
    39         g[u].push_back(v);
    40         g[v].push_back(u);
    41     }
    42     for(int i=1; i<=n; i++)
    43         cin >> a[i];
    44     dfs(1,-1);
    45 
    46     cout << up[1]+down[1] << endl;
    47 
    48     return 0;
    49 }
  • 相关阅读:
    剑指17.树的子结构
    剑指16.合并两个排序的链表
    剑指15.反转链表
    剑指14.链表中倒数第k个结点
    剑指13.调整数组顺序使奇数位于偶数前面
    剑指12.数值的整数次方
    剑指11.二进制中1的个数
    剑指10.矩形覆盖
    剑指09.变态跳台阶
    JS 中动态创建json,动态为json添加属性、属性值
  • 原文地址:https://www.cnblogs.com/yxg123123/p/6941193.html
Copyright © 2011-2022 走看看