• F. Tree with Maximum Cost(换根)


    F. Tree with Maximum Cost

     

     

    学习博客:https://blog.csdn.net/LJD201724114126/article/details/85240762?utm_source=app

    题解:换根

    我们先设sum[u] 等于 以u为根的子树的∑ai (注意没有*距离),再计算以1为根的贡献值res。

    这时我们要从父亲节点u向儿子节点v换根,故需要将res的值转化为以v为根的value

     

    首先我们要先 res -= sum[v],因为换根之前,以v为根的子树(包括v)到原根u的深度比换根之后,到新根v的深度少了一,故减去

    然后我们sum[u] -= sum[v],因为原来sum[u]表示的是以u为根的值(包括了以v为根),而这时是以v为根的,故sum[u]要减去sum[v],

    res += sum[u],因为换根之前,以u为根的子树(包括u)到原根u的深度比换根之后,到新根v的深度多了一,故加上

    最后sum[v]+=sum[u],因为v要成为整个树的根,而原来sum[v]不包括以u为根的节点值,故要加上。

    换完之后我们再换回来。

    这里巧妙的应用了换根,就是先求出任意一个根的结果,然后我们dfs,将相邻的根换一换,求出结果。

    AC_Code

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 2e5+10;
     5 const int inf=0x3f3f3f3f;
     6 #define rep(i,first,last) for(ll i=first;i<=last;i++)
     7 #define dep(i,first,last) for(ll i=first;i>=last;i--)
     8 struct edge{ll to,nxt;}e[maxn<<1];
     9 ll head[maxn<<1],cnt,a[maxn],n;
    10 ll ans,res,sum[maxn];
    11 void addedge(ll u,ll v){ e[++cnt].to=v; e[cnt].nxt=head[u];head[u]=cnt;}
    12 void dfs1(ll u,ll fa,ll h){
    13     res+=(h*a[u]);
    14     sum[u]=a[u];
    15     for(ll i=head[u];i;i=e[i].nxt){
    16         ll v=e[i].to;
    17         if(v==fa) continue;
    18         dfs1(v,u,h+1);
    19         sum[u]+=sum[v];
    20     }
    21 }
    22 void dfs2(ll u,ll fa){
    23     ans=max(ans,res);
    24     for(ll i=head[u];i;i=e[i].nxt){
    25         ll v=e[i].to;
    26         if( v==fa ) continue;
    27 
    28         res-=sum[v];
    29         sum[u]-=sum[v];
    30         res+=sum[u];
    31         sum[v]+=sum[u];
    32 
    33         dfs2(v,u);
    34 
    35         sum[v]-=sum[u];
    36         res-=sum[u];
    37         sum[u]+=sum[v];
    38         res+=sum[v];
    39     }
    40     return ;
    41 }
    42 signed main()
    43 {
    44     scanf("%lld",&n);
    45     rep(i,1,n) scanf("%lld",&a[i]);
    46     ll x,y;
    47     rep(i,1,n-1){
    48         scanf("%lld%lld",&x,&y);
    49         addedge(x,y);
    50         addedge(y,x);
    51     }
    52     dfs1(1,-1,0);
    53     dfs2(1,-1);
    54     printf("%lld
    ",ans);
    55     return 0;
    56 }
  • 相关阅读:
    CSS3背景
    CSS3嵌入字体
    CSS3控制单行文本的溢出
    CSS3渐变色彩
    CSS3图片边框
    CSS中的各类选择器
    HTML 5入门知识——Drag
    今天是星期五,昨天下午回来之前,公司的人员都等施佳回来开会讨论需求
    这些天晚上有点睡不好,也是关于一个事情
    昨天回来后11点的时候吧午饭弄了
  • 原文地址:https://www.cnblogs.com/wsy107316/p/12345748.html
Copyright © 2020-2023  润新知