[CF274B]Zero Tree

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章