Codeforces Round 1286B #612 (Div. 1) B. Numbers on Tree 解题思路 - DFS&构造&线段树

博客详细介绍了Codeforces Round #612 (Div. 1) B题——Numbers on Tree的解题思路,主要涉及如何根据树的结构和给定的子节点小于当前节点的条件,使用DFS和构造方法恢复节点上的初始整数。如果存在解决方案,输出“YES”并给出整数;否则输出“NO”。
摘要由CSDN通过智能技术生成

Codeforces Round #612 (Div. 1) B. Numbers on Tree

Evlampiy was gifted a rooted tree. The vertices of the tree are numbered from 1 to 𝑛. Each of its vertices also has an integer 𝑎𝑖 written on it. For each vertex 𝑖, Evlampiy calculated 𝑐𝑖 — the number of vertices 𝑗 in the subtree of vertex 𝑖, such that 𝑎𝑗<𝑎𝑖.
在这里插入图片描述
Illustration for the second example, the first integer is 𝑎𝑖 and the integer in parentheses is 𝑐𝑖.

After the new year, Evlampiy could not remember what his gift was! He remembers the tree and the values of 𝑐𝑖, but he completely forgot which integers 𝑎𝑖 were written on the vertices.

Help him to restore initial integers!

Input

The first line contains an integer 𝑛 (1≤𝑛≤2000) — the number of vertices in the tree.

The next 𝑛 lines contain descriptions of vertices: the 𝑖-th line contains two integers 𝑝𝑖 and 𝑐𝑖 (0≤𝑝𝑖≤𝑛; 0≤𝑐𝑖≤𝑛−1), where 𝑝𝑖 is the parent of vertex 𝑖 or 0 if vertex 𝑖 is root, and 𝑐𝑖 is the number of vertices 𝑗 in the subtree of vertex 𝑖, such that 𝑎𝑗<𝑎𝑖.

It is guaranteed that the values of 𝑝𝑖 describe a rooted tree with 𝑛 vertices.

Output

If a solution exists, in the first line print “YES”, and in the second line output 𝑛 integers 𝑎𝑖 (1≤𝑎𝑖≤109). If there are several solutions, output any of them. One can prove that if there is a solution, then there is also a solution in which all 𝑎𝑖 are between 1 and 109.

If there are no solutions, print “NO”.

已知树的结构,要求为每个节点赋值,使得每个节点的子节点小于当前节点的个数为给定值。如果不能构造输出“NO”。

解题思路:
设有一段数字序列初始化为1到n个值,定义操作find_k(int k)返回这个序列的第k大的值,并且每个值只返回一次。
从根节点往下DFS。
此时已知根节点小于它的个数,假设为k,则设置此节点的值为k+1。因为每个节点都会赋值的,所以前k个数一定会赋值在某个节点上,所以可以被满足。
假设根节点有n个子节点,则依次为每个节点赋值,保证根节点的第1个孩子节点的所有子孙节点的值小于第2个孩子节点的所有子孙节点的值,第2个孩子节点的所有子孙节点的值小于第3个孩子节点的所有子孙节点的值,,,第n-1个孩子节点的所有子孙节点的值小于第n个孩子节点的所有子孙节点的(关键点是在一串数字序列中返回第k+1大的那个值)。
对于每个孩子节点进行以上操作即可构造出一个结果。

/// @author zhaolu

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <set>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值