51nod 1424:零树

51nod1424零树题解
本文解析了51nod1424题目的解决方案,该题涉及一棵树的操作,目标是最少次数地调整节点值使其归零。采用树形DP算法,定义状态dp[u][j]来求解最小操作数,并给出完整代码实现。

51nod 1424:零树

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1424

题目大意:有一颗大小为$n(1 \leqslant n \leqslant 10^5)$的树,根结点为$1$。现每次可以选择一个包含根结点的连通块,将此连通块内的点的值均$+1$或$-1$,问使整棵树的结点均为$0$最少需要多少次操作。

树形DP

定义状态$dp[u][j]$为将结点$u$及其子树清空至少需要$+1$和$-1$的操作数,则有

转移方程$dp[u][j]=max\{dp[v][j]\}$($v$为$u$的孩子),$dp[u][d<0]+=abs(d)$,其中$d=dp[u][1]-dp[u][0]+c[u]$为将结点$u$清空还需要的操作数.

注意答案会爆int.复杂度为$O(n)$.

代码如下:

 1 #include <cstdio>
 2 #include <vector>
 3 #include <cmath>
 4 #define N 100005
 5 using namespace std;
 6 typedef long long ll;
 7 ll dp[N][2],n,x,y,c[N];
 8 vector<int>e[N];
 9 void dfs(int u,int f){
10     for(int i=0;i<(int)e[u].size();++i){
11         int v=e[u][i];
12         if(v!=f){
13             dfs(v,u);
14             dp[u][1]=max(dp[u][1],dp[v][1]);
15             dp[u][0]=max(dp[u][0],dp[v][0]);
16         }
17     }
18     ll d=dp[u][1]-dp[u][0]+c[u];
19     dp[u][d<0]+=abs(d);
20 }
21 int main(void){
22     scanf("%lld",&n);
23     for(int i=1;i<n;++i){
24         scanf("%d%d",&x,&y);
25         e[x].push_back(y);
26         e[y].push_back(x);
27     }
28     for(int i=1;i<=n;++i)
29         scanf("%lld",&c[i]);
30     dfs(1,0);
31     printf("%lld\n",dp[1][0]+dp[1][1]);
32 }

 

转载于:https://www.cnblogs.com/barrier/p/6734419.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值