D. Numbers on Tree 构造,树dfs

题目链接:https://codeforces.com/contest/1287/problem/D

D. Numbers on Tree

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

Evlampiy was gifted a rooted tree. The vertices of the tree are numbered from 11 to nn. Each of its vertices also has an integer aiai written on it. For each vertex ii, Evlampiy calculated cici — the number of vertices jj in the subtree of vertex ii, such that aj<aiaj<ai.

Illustration for the second example, the first integer is aiai and the integer in parentheses is cici

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

Help him to restore initial integers!

Input

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

The next nn lines contain descriptions of vertices: the ii-th line contains two integers pipi and cici (0≤pi≤n0≤pi≤n; 0≤ci≤n−10≤ci≤n−1), where pipi is the parent of vertex ii or 00 if vertex ii is root, and cici is the number of vertices jj in the subtree of vertex ii, such that aj<aiaj<ai.

It is guaranteed that the values of pipi describe a rooted tree with nn vertices.

Output

If a solution exists, in the first line print "YES", and in the second line output nn integers aiai (1≤ai≤109)(1≤ai≤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 aiai are between 11 and 109109.

If there are no solutions, print "NO".

Examples

input

Copy

3
2 0
0 2
2 0

output

Copy

YES
1 2 1 

input

Copy

5
0 1
1 3
2 1
3 0
2 0

output

Copy

YES
2 3 2 1 2

题意:

给定一个含有n个节点的tree,每一个节点上有一个数值a[i],以及一个数组c,

c[i]代表在以节点i为根的子树中,数值小于a[i]的节点个数为c[i]

请构造出满足c[i] 条件的数组a。

如果无法构造出满足条件的数组a,输出NO。

否则输出 YES以及数组a

思路:

判断是否可以构造出数组a:

​ 数组sz[i], 代表第i个节点为根的子树的节点个数。如果存在一个节点i,使c[i]>sz[i]-1 ,那么无法构造出符合条件的。

当可以构造出时,我们来构造数组a:

从树根开始树形dfs,每次给当前点赋的值就是还没有用到的数字中第c[u]个数字(从0开始数)

这种做法的正确性在于:

首先当前数字是第c[u]个,那么,只要前面c[u]-1个数字如果都是该点的孩子的值,那么答案成立。由于孩子的数量大于等于c[u],给孩子赋值又是按照顺序来,所以前面几个数字一定会赋给它的孩子。

 代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) { if (a == 0ll) {return 0ll;} a %= MOD; ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}


const int maxn = 3010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
std::vector<int> son[maxn];
int n;
int rt;
int c[maxn];
int x, y;
int ans[maxn];
std::vector<int> v[maxn];
int isok = 1;
int base = 1;
int sz[maxn];
int vis[maxn];

void dfs(int now, int pre)
{
    sz[now] = 1;
    if (!isok)
    {
        return ;
    }
    int pos = 0;
    repd(i, 1, n)
    {
        if (!vis[i])
        {
            if (pos == c[now])
            {
                vis[i] = 1;
                ans[now] = i;
                break;
            }
            pos++;
        }
    }
    for (auto to : son[now])
    {
        if (to != pre)
        {
            dfs(to, now);
            sz[now] += sz[to];
        }
    }
    if (c[now] > sz[now] - 1)
    {
        isok = 0;
    }
}
int main()
{
//freopen("D:\\code\\text\\input.txt","r",stdin);
//freopen("D:\\code\\text\\output.txt","w",stdout);
    gbtb;
    cin >> n;
    repd(i, 1, n)
    {
        cin >> x >> y;
        if (!x)
        {
            rt = i;
        } else
        {
            son[x].push_back(i);
            son[i].push_back(x);
        }
        c[i] = y;
    }
    dfs(rt, -1);
    if (isok)
    {
        cout << "YES" << endl;
        repd(i, 1, n)
        {
            cout << ans[i];
            if (i == n)
            {
                cout << endl;
            } else
            {
                cout << " ";
            }
        }
    } else
    {
        cout << "NO" << endl;
    }

    return 0;
}