考试

题目

题目描述
W 作为一名新时代社会主义接班人, 励志为了环境美好而积极种树。 以至于他在 OI
中一看到树就兴奋。
现在, 他有一棵 n 个节点、 n-1 条边的树。 这个树的节点有大有小。 小 W 把正常大小,
为了便于衡量, 小 W 把正常大小的节点参考值设为 0, 于是便有参考值为负数的小节点,
以及参考值为正数的大节点。
作为强迫症患者, 小 W 想要把所有的节点大小全部变为正常大小。 每次操作, 小 W
以将任一个联通子图内的节点大小都+1 -1。 但是这个联通子图必须包含 1 号节点。
所以小 W 想让你帮忙求出最少执行几次操作能够满足小 W 的要求。
输入
第一行一个正整数 n, 代表树的节点数。
接下来 n-1 行, 每行两个正整数 xy, 描述树上的一条边。
接下来一行 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<=100000Tiint 范围内。
资源限制
每个测试点空间限制 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;
}

  

  

  

原文地址:https://www.cnblogs.com/eric-walker/p/9403934.html