题目
题目描述
小 W 作为一名新时代社会主义接班人, 励志为了环境美好而积极种树。 以至于他在 OI
中一看到树就兴奋。
现在, 他有一棵 n 个节点、 n-1 条边的树。 这个树的节点有大有小。 小 W 把正常大小,
为了便于衡量, 小 W 把正常大小的节点参考值设为 0, 于是便有参考值为负数的小节点,
以及参考值为正数的大节点。
作为强迫症患者, 小 W 想要把所有的节点大小全部变为正常大小。 每次操作, 小 W 可
以将任一个联通子图内的节点大小都+1 或-1。 但是这个联通子图必须包含 1 号节点。
所以小 W 想让你帮忙求出最少执行几次操作能够满足小 W 的要求。
输入
第一行一个正整数 n, 代表树的节点数。
接下来 n-1 行, 每行两个正整数 x, y, 描述树上的一条边。
接下来一行 n 个整数, 第 i 个整数为节点 i 的大小 Ti。
输出
输出 1 个整数表示最少操作次数。
输入样例
3 1
2
1 3
1 -1 1
输出样例
3 数
据规模与约定
对不超过 0%的数据, 保证与样例完全一样;
对 10%的数据, 保证 n<=5;
对另外 20%的数据, 保证 x=1;
对另外 20%的数据, 保证 y=x+1;
对 100%的数据, 保证 n<=100000, Ti在 int 范围内。
资源限制
每个测试点空间限制 256MB, 时间限制 1s。
简单的树形dp(水题)
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; #define int long long const int maxn=1e5+5; struct ED{ int to; ED *nt; }ed[maxn<<2]; ED*head[maxn]; ED* ent=ed; int t[maxn],f[maxn][2]; void add(int x,int y){ ED* p=++ent; p->to=y; p->nt=head[x]; head[x]=p; } void dfs(int x,int fa){ int tmp[2]={0,0},tmpt=t[x]; for(ED* i=head[x];i;i=i->nt){ if(i->to!=fa){ dfs(i->to,x); tmp[0]=max(tmp[0],f[i->to][0]); tmp[1]=max(tmp[1],f[i->to][1]); } } f[x][0]=tmp[0];f[x][1]=tmp[1]; tmpt=tmpt+tmp[0]-tmp[1]; if(tmpt<0)f[x][0]+=-tmpt;//需要加上的 if(tmpt>0)f[x][1]+= tmpt;//需要减去的 } int n; signed main(){ #ifndef nFILE freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); #endif cin>>n; for(int i=1;i<n;++i){ int x,y; cin>>x>>y; add(x,y);add(y,x); } for(int i=1;i<=n;++i){ cin>>t[i]; } dfs(1,0); cout<<f[1][0]+f[1][1]<<endl; return 0; }