[CF274B]Zero Tree

来源:互联网 发布:张仪 楚怀王 知乎 编辑:程序博客网 时间:2024/06/17 09:38

CF274B:Zero Tree

题目简述

给出一棵n个结点的带点权的树。每次可以选择包括根节点的一个连通块,令这个连通块中所有点的权值+1/1。问最少多少步才能使所有点的点权为0

数据范围

1n105
1|vi|109

思路

树形DP。
每次相当于是从当前点到根沿路打了加减标记。
f[i]表示以i为根的子树需要加的值。
g[i]表示以i为根的子树需要减的值。
DP时候先加上孩子的贡献,再算出它往上的贡献。
转移看代码= =

代码

#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>using namespace std;struct edge{    int s,t,next;}e[200010];int head[100010],cnt;void addedge(int s,int t){    e[cnt].s=s;e[cnt].t=t;e[cnt].next=head[s];head[s]=cnt++;    e[cnt].s=t;e[cnt].t=s;e[cnt].next=head[t];head[t]=cnt++;}int n,u,v;long long val[100010],f[100010],g[100010];void dfs(int node,int lastfa){    f[node]=g[node]=0;    for (int i=head[node];i!=-1;i=e[i].next)        if (e[i].t!=lastfa)        {            dfs(e[i].t,node);            f[node]=max(f[node],f[e[i].t]);            g[node]=min(g[node],g[e[i].t]);        }    val[node]+=f[node]+g[node];    if (val[node]>0)        g[node]-=val[node];    else        f[node]-=val[node];}int main(){    scanf("%d",&n);    memset(head,0xff,sizeof(head));    for (int i=1;i<n;i++)    {        scanf("%d%d",&u,&v);        addedge(u,v);    }    for (int i=1;i<=n;i++)        scanf("%I64d",&val[i]);    dfs(1,1);    printf("%I64d\n",abs(f[1])+abs(g[1]));    return 0;}
0 0