您的位置:首页 > 其它

51nod 1424 零树(树DP)

2017-09-09 09:19 357 查看
1424 零树


题目来源: CodeForces

基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题


 收藏


 关注

有一棵以1为根的树,他有n个结点,用1到n编号。第i号点有一个值vi。

现在可以对树进行如下操作:

步骤1:在树中选一个连通块,这个连通块必须包含1这个结点。

步骤2:然后对这个连通块中所有结点的值加1或者减1。

问最少要经过几次操作才能把树中所有结点都变成0。

注意:步骤1与步骤2合在一起为一次操作。

Input
单组测试数据。
第一行有一个整数n(1 ≤ n ≤ 10^5)
接下来n-1行,每行给出 ai 和 bi (1 ≤ ai, bi ≤ n; ai ≠ bi),表示ai和bi之间有一条边,输入保证是一棵树。
最后一行有n个以空格分开的整数,表示n个结点的值v1, v2, ..., vn (|vi| ≤ 10^9)。


Output
输出一个整数表示最少的操作步数。.


Input示例
3
1 2
1 3
1 -1 1


Output示例
3


解:因为更改子树一定会影响根节点,所以找到影响最大的那个子树节点就可以了

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<map>
#include <set>
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
typedef long long LL;
typedef pair<int,int>pi;
const LL mod = 1e9+7;
struct node
{
int to, next;
}p[N*2];
int head
, in
, cnt, vis
;
void init()
{
memset(head,-1,sizeof(head));
memset(in,0,sizeof(in));
memset(vis,0,sizeof(vis));
cnt=0;
return ;
}
void add(int u,int v)
{
p[cnt].to=v,p[cnt].next=head[u];head[u]=cnt++;
p[cnt].to=u,p[cnt].next=head[v];head[v]=cnt++;
return ;
}
LL dp
[2], a
;
void dfs(int u,int f)
{
for(int i=head[u];i!=-1;i=p[i].next)
{
int v=p[i].to;
if(v==f) continue;
dfs(v,u);
dp[u][0]=max(dp[u][0],dp[v][0]);
dp[u][1]=max(dp[u][1],dp[v][1]);
}
LL x=a[u]-dp[u][0]+dp[u][1];
if(x<0) dp[u][1]+=abs(x);
else dp[u][0]+=x;
return ;
}

int main()
{
int n;
scanf("%d", &n);
init();
for(int i=1;i<n;i++)
{
int x, y;
scanf("%d %d", &x, &y);
add(x,y);
}
for(int i=1;i<=n;i++)
scanf("%lld", &a[i]);
memset(dp,0,sizeof(dp));
dfs(1,-1);
printf("%lld\n",dp[1][0]+dp[1][1]);
return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: