【题目】
题目描述:
你的防线成功升级,从原来的一根线变成了一棵树。这棵树有 个炮台,炮台与炮台之间有 条隧道。
你要选择一些炮台安装哨戒炮。在第 个炮台上安装哨戒炮得到的防御力为 。上次说过,哨戒炮离得太近会产生神奇的效果。具体来说,对于炮台 ,如果它安装了哨戒炮且和 个哨戒炮用隧道直接相连,那么其防御力会变化 。其中 为炮台 的抗干扰属性值。如果为正,干扰对其有正的作用;为负,干扰对其有负的作用;为 ,则完全不受干扰。
你的整套防线的防御力为所有哨戒炮的防御力之和。求防线的最大防御力。
输入格式:
第一行一个整数 ,表示炮台数量。
第二行 个整数表示 。
第三行 个整数表示 。
接下来 行每行两个整数描述一条隧道。
输出格式:
输出一行一个整数表示答案
样例数据:
输入
2
1 1
0 0
1 2
输出
2
提示:
对于
的数据,
。
对于
的数据,
。
对于
的数据,
。
对于
的数据,
。
【分析】
这是今天考的最简单的一道题啦,只不过不写 就只有 分啦。
很明显的树形 ,用 表示在 的子树内,选 不选 的最大防御力。
那么显然的(设 为 的儿子结点):
最后的答案 。
【代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define ll long long
using namespace std;
int n,t,v[N],d[N];
int first[N],V[N<<1],nxt[N<<1];
ll f[N][2];
void add(int x,int y)
{
nxt[++t]=first[x];
first[x]=t,V[t]=y;
}
void dp(int x,int father)
{
int i,k;
f[x][1]=v[x],f[x][0]=0;
for(i=first[x];i;i=nxt[i])
{
k=V[i];
if(k!=father)
{
dp(k,x);
f[x][1]+=max(f[k][0],f[k][1]+d[k]+d[x]);
f[x][0]+=max(f[k][0],f[k][1]);
}
}
}
int main()
{
int x,y,i;
scanf("%d",&n);
for(i=1;i<=n;++i) scanf("%d",&v[i]);
for(i=1;i<=n;++i) scanf("%d",&d[i]);
for(i=1;i<n;++i)
{
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
dp(1,0);
printf("%lld",max(f[1][1],f[1][0]));
return 0;
}