给定一棵 n 个节点组成的树。
树中节点编号为 1∼n。
1 号节点为树的根节点。
树中的每个节点 vv 都具有一个非负整数权值 av。
我们用 sv 来表示从节点 v 到根节点的路径上经过的所有节点(包括两端节点)的权值之和;用 hv 来表示从节点 v 到根节点的路径上经过的所有节点(包括两端节点)的数量。
显然,s1=a1,h1=1。
现在,我们只知道树的具体结构以及所有 h 值为奇数的节点的 s 值。
请你为树中的每个节点 v 赋予一个非负整数权值 av,要求在满足已知信息的情况下,所有节点的权值之和 ∑i=1nai尽可能小。
输出 ∑i=1nai 的最小可能值。
输入格式
第一行包含一个整数 n。
第二行包含 n−1 个整数 p2,p3,…,pn,其中 pi表示节点 i 的父节点编号。
第三行包含 n 个整数 s1,s2,…,sn,注意,由于所有 h 值为偶数的节点的 s 值都是未知的,所以这些节点的 s 值并未直接给出,而是用 −1 来代替。
输出格式
一个整数,表示 ∑i=1nai 的最小可能值。
如果不存在任何满足已知信息的合理赋值方案,则输出 −1。
数据范围
前 44 个测试点满足 2≤n≤5。
所有测试点满足 2≤n≤105,1≤pi<i,−1≤si≤109。
输入样例1:
5
1 1 1 1
1 -1 -1 -1 -1
输出样例1:
1
输入样例2:
5
1 2 3 1
1 -1 2 -1 -1
输出样例2:
2
输入样例3:
3
1 2
2 -1 1
输出样例3:
-1
分析:自己写的时候感觉像是在写一个模拟,就根据提意模拟出来就可以了,其实前面的值都有点固定,把没有子节点的h 值为偶数 的节点的值设为零就是最小了,遍历的时候记得奇偶分情况讨论;
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int s[N],w[N];
vector<int>adj[N];
int n,flag;
long long ans;
void dfs(int s1,int u,int a)
{
if(a)
{
for(auto v:adj[u])
{
dfs(s[u],v,0);
}
return;
}
int minn=1e9;
for(auto v:adj[u])
{
if(s[v]-s1<0)
{
flag=1;
return;
}
minn=min(minn,s[v]-s1);
}
if(minn!=1e9) w[u]=minn;
for(auto v:adj[u])
{
w[v]=s[v]-s1-w[u];
dfs(0,v,1);
}
}
int main()
{
cin>>n;
for(int i=2;i<=n;i++)
{
int x;
cin>>x;
adj[x].push_back(i);
}
for(int i=1;i<=n;i++)cin>>s[i];
w[1]=s[1];
dfs(0,1,1);
if(flag)cout<<-1;
else
{
for(int i=1;i<=n;i++)ans+=w[i];
cout<<ans;
}
return 0;
}