CF1098A Sum in the tree 题解 树+贪心

Sum in the tree

传送门

Mitya has a rooted tree with n n n vertices indexed from 1 1 1 to n n n, where the root has index 1 1 1. Each vertex v v v initially had an integer number a v ≥ 0 a_v \ge 0 av0 written on it. For every vertex v v v Mitya has computed s v s_v sv: the sum of all values written on the vertices on the path from vertex v v v to the root, as well as h v h_v hv — the depth of vertex v v v, which denotes the number of vertices on the path from vertex v v v to the root. Clearly, s 1 = a 1 s_1=a_1 s1=a1 and h 1 = 1 h_1=1 h1=1.

Then Mitya erased all numbers a v a_v av, and by accident he also erased all values s v s_v sv for vertices with even depth (vertices with even h v h_v hv). Your task is to restore the values a v a_v av for every vertex, or determine that Mitya made a mistake. In case there are multiple ways to restore the values, you’re required to find one which minimizes the total sum of values a v a_v av for all vertices in the tree.

Input

The first line contains one integer n n n — the number of vertices in the tree ( 2 ≤ n ≤ 1 0 5 2 \le n \le 10^5 2n105). The following line contains integers p 2 p_2 p2, p 3 p_3 p3, … p n p_n pn, where p i p_i pi stands for the parent of vertex with index i i i in the tree ( 1 ≤ p i < i 1 \le p_i < i 1pi<i). The last line contains integer values s 1 s_1 s1, s 2 s_2 s2, …, s n s_n sn ( − 1 ≤ s v ≤ 1 0 9 -1 \le s_v \le 10^9 1sv109), where erased values are replaced by − 1 -1 1.

Output

Output one integer — the minimum total sum of all values a v a_v av in the original tree, or − 1 -1 1 if such tree does not exist.

Examples

input #1

5
1 1 1 1
1 -1 -1 -1 -1

output #1

1

input #2

5
1 2 3 1
1 -1 2 -1 -1

output #2

2

input #3

3
1 2
2 -1 1

output #3

-1

题目翻译

米迪亚有一棵有根的树,树上有 n n n 个顶点,索引从 1 1 1 n n n ,其中根的索引为 1 1 1 。每个顶点 v v v 最初都写有一个整数 a v ≥ 0 a_v \ge 0 av0 。对于每个顶点 v v v 米迪亚计算了 s v s_v sv :从顶点 v v v 到根的路径上写在顶点上的所有值的总和,以及 h v h_v hv - 顶点 v v v 的深度,即从顶点 v v v 到根的路径上的顶点数。显然, s 1 = a 1 s_1=a_1 s1=a1 h 1 = 1 h_1=1 h1=1

然后米迪亚删除了所有数字 a v a_v av ,并且意外地删除了偶数深度顶点(偶数顶点 h v h_v hv )的所有数值 s v s_v sv 。你的任务是恢复每个顶点的值 a v a_v av ,或者确定 Mitya 犯了一个错误。如果有多种还原数值的方法,你需要找到一种,使树中所有顶点的数值总和 a v a_v av 最小。

输入格式

第一行包含一个整数 n n n - 树的顶点数( 2 ≤ n ≤ 1 0 5 2 \le n \le 10^5 2n105 )。下面一行包含整数 p 2 p_2 p2 , p 3 p_3 p3 , … p n p_n pn ,其中 p i p_i pi 代表树中索引为 i i i 的顶点的父顶点( 1 ≤ p i < i 1 \le p_i < i 1pi<i )。最后一行包含整数值 s 1 s_1 s1 s 2 s_2 s2 、…、 s n s_n sn − 1 ≤ s v ≤ 1 0 9 -1 \le s_v \le 10^9 1sv109 ),其中已删除的值由 − 1 -1 1 代替。

输出格式

输出一个整数 - 原始树中所有值 a v a_v av 的最小总和,如果不存在这样的树,则输出 − 1 -1 1

注明

以上来自 C o d e F o r c e s ,翻译: D e e p L 以上来自CodeForces,翻译:DeepL 以上来自CodeForces,翻译:DeepL

解题思路

简要解释一下题意:给出一棵以 1 1 1 为根节点的树,大小为 n n n。记根节点深度为 1 1 1。树上每个节点都有一个非负权值 a i a_i ai(不给出),记 s i s_i si 表示从 i i i 号节点到根节点的路径上所有点的权值和,包括根节点及其本身
现在给你每个深度为奇数节点的 s i s_i si。深度为偶数的节点的 s i s_i si 不给出,值为 − 1 −1 1。请你还原树的每个节点的权值。使得其满足所有给出的值不为 − 1 -1 1 s i s_i si。并输出最小的 Σ a i \Sigma a_i Σai。若无解,则输出 −1。

想一想就能明白,让一个 a i a_i ai 尽可能的去给更多的 s i s_i si 做贡献,即可使 Σ a i \Sigma a_i Σai 最小。所以对每个 − 1 -1 1 s i s_i si 搜索出其孩子中的最小 s i s_i si(因为要求每个子节点 s i s_i si 总会大于父节点 s i s_i si),最后判断如果有子节点 s i s_i si 小于父节点 s i s_i si,则输出 − 1 -1 1

AC Code

#include<bits/stdc++.h>
using namespace std;
char buf[1048576], *p1, *p2;
template<typename T>inline void Super_Quick_Read(T &x) {
	bool f = 1;
	x = 0;
	char ch = (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) ? 0 : *p1++);
	while (ch < '0' || ch > '9') {
		if (ch == '-') f = !f;
		ch = (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) ? 0 : *p1++);
	}
	while (ch >= '0' && ch <= '9')x = (x << 1) + (x << 3) + (ch ^ 48), ch = (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) ? 0 : *p1++);
	x = (f ? x : -x);
	return;
}
template<typename T>inline void Quick_Write(T x) {
	if (x < 0) putchar('-'), x = -x;
	if (x > 9) Quick_Write(x / 10);
	putchar(x % 10 + '0');
	return;
}
int n;
long long s[200005];
int U[200005], V[200005], W[200005], Fst[200005], Next[200005], Father[200005], Length;
long long Answer = 0;
inline void Add(int a, int b) {
	U[++Length] = a, V[Length] = b, Next[Length] = Fst[a], Fst[a] = Length;
}
inline long long Dfs(int n) {
	if (s[n] != -1)	return s[n];
	else {
		int k = Fst[n];
		long long _min = 1e9 + 5;
		while (k != -1)_min = min(Dfs(V[k]), _min), k = Next[k];
		s[n] = _min;
		return s[n];
	}
}
signed main() {
	Super_Quick_Read(n);
	for (register int i = 0; i <= n + 1; i++)Fst[i] = -1;
	for (register int i = 2, t; i <= n; ++i)Super_Quick_Read(t), Add(t, i), Father[i] = t;
	for (register int i = 1; i <= n; ++i)Super_Quick_Read(s[i]);
	int flag = 0;
	for (register int i = 1, t1, t2; i <= n; ++i) {
		t1 = Dfs(i), t2 = Dfs(Father[i]);
		if (t1 != 1e9 + 5) {
			if (t2 > t1)flag = 1;
			Answer += (t1 - t2);
		}
	}
	if (flag)puts("-1");
	else Quick_Write(Answer);
	return 0;
}

重要提醒

CSDN你什么时候完善你的 L a T e X LaTeX LaTeX 公式显示啊!

  • 28
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值