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
Output
Input示例
Output示例
解:因为更改子树一定会影响根节点,所以找到影响最大的那个子树节点就可以了
#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;
}
题目来源: 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;
}
相关文章推荐
- 51nod 1424 零树(树形dp)
- 51nod 1424 零树(树dp)
- 51nod 1020:逆序排列 DP
- 51Nod 1092 回文字符串(LCS跟dp)
- 51nod 1405 树的距离之和 (两次dfs,树形dp)
- 51Nod - 1051 最大子矩阵和(dp)
- 51nod 1398 等公交【概率DP】
- 51nod 1781 Pinball【DP】【线段树】
- 【51Nod】1042 - 数字0-9的数量(数位dp & 递归)
- 51nod 1202 线性dp
- 51nod 1391 01串 (dp+hash)
- 【dp】51nod 1201 整数划分
- 51nod 1201:整数划分 超级好的DP题目
- 51nod 1378 夹克老爷的愤怒(树DP+贪心)
- 51nod 正整数分组(dp_思考题)
- 【51nod 1684】子集价值【DP】【拆括号的技巧】
- 51nod 1603 限高二叉排列树(求补思想->DP)
- [dp专题-四边形不等式优化]51nod 1022
- 51nod 1270 数组的最大代价 (DP_好题)
- 51Nod 1042 数字0-9的数量 (数位DP