【2019/03/30测试T2】哨戒炮 II

【题目】

传送门

题目描述:

你的防线成功升级,从原来的一根线变成了一棵树。这棵树有 n n n 个炮台,炮台与炮台之间有 n − 1 n-1 n1 条隧道。

你要选择一些炮台安装哨戒炮。在第 i i i 个炮台上安装哨戒炮得到的防御力为 v i v_i vi。上次说过,哨戒炮离得太近会产生神奇的效果。具体来说,对于炮台 i i i,如果它安装了哨戒炮且和 k k k 个哨戒炮用隧道直接相连,那么其防御力会变化 k × d i k\times d_i k×di。其中 d i d_i di 为炮台 i i i 的抗干扰属性值。如果为正,干扰对其有正的作用;为负,干扰对其有负的作用;为 0 0 0,则完全不受干扰。

你的整套防线的防御力为所有哨戒炮的防御力之和。求防线的最大防御力。

输入格式:

第一行一个整数 n n n,表示炮台数量。

第二行 n n n 个整数表示 v i v_i vi

第三行 n n n 个整数表示 d i d_i di

接下来 n − 1 n-1 n1 行每行两个整数描述一条隧道。

输出格式:

输出一行一个整数表示答案

样例数据:

输入
2
1 1
0 0
1 2

输出
2

提示:

对于 20 % 20\% 20% 的数据, n ≤ 20 n \le 20 n20
对于 40 % 40\% 40% 的数据, n ≤ 100 n \le 100 n100
对于 70 % 70\% 70% 的数据, n ≤ 5000 n \le 5000 n5000
对于 100 % 100\% 100% 的数据, n ≤ 100000 n \le 100000 n100000


【分析】

这是今天考的最简单的一道题啦,只不过不写 l o n g    l o n g \mathrm{long} \;\mathrm{long} longlong 就只有 0 0 0 分啦。

很明显的树形 D P \mathrm{DP} DP,用 f i , 0 / 1 f_{i,0/1} fi,0/1 表示在 i i i 的子树内,选 / / /不选 i i i 的最大防御力。

那么显然的(设 j j j i i i 的儿子结点):

f i , 1 = ∑ m a x ( f j , 0 , f j , 1 + d j + d i ) + v i f_{i,1}=\sum max(f_{j,0},f_{j,1}+d_j+d_i)+v_i fi,1=max(fj,0,fj,1+dj+di)+vi

f i , 0 = ∑ m a x ( f j , 0 , f j , 1 ) f_{i,0}=\sum max(f_{j,0},f_{j,1}) fi,0=max(fj,0,fj,1)

最后的答案 a n s = m a x ( f 1 , 0 , f 1 , 1 ) ans=max(f_{1,0},f_{1,1}) ans=max(f1,0,f1,1)


【代码】

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值