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