题目链接:https://codeforces.com/contest/1287/problem/D
题意:
n个节点的树,每个节点有ai和ci ai是节点i的值,ci表示i的所有子节点中,有ci个值比它小的 现在给树的形态(每个节点的父节点pre)和每个节点的ci,要求构造出一组ai满足条件 如果能构造出输出YES和ai 否则输出NO
想法:
我们不难知道当前节点 u 的点权只对它的子树中的节点的点权有影响,所以我们应该从上自下去遍历整棵树。
我们从顶点开始放,没放的数字我们是一定知道的(因为只有1-n)。所以放的时候相当于在没放的数字中找到第c[i]+1大的数字,放上去。即可满足条件,继续向下递归。
#include <algorithm> #include <string> #include <string.h> #include <vector> #include <map> #include <stack> #include <set> #include <queue> #include <math.h> #include <cstdio> #include <iomanip> #include <time.h> #include <bitset> #include <cmath> #include <sstream> #include <iostream> #include <cstring> #define LL long long #define ls nod<<1 #define rs (nod<<1)+1 #define pii pair<int,int> #define mp make_pair #define pb push_back #define INF 0x3f3f3f3f const double eps = 1e-10; const int maxn = 2000 + 10; const LL mod = 1e9 + 7; int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;} using namespace std; struct edge{ int v,nxt; }e[maxn<<1]; int cnt; int head[maxn]; int c[maxn],siz[maxn],p[maxn]; int vis[maxn]; int tot,n; inline void add_edge(int u,int v) { e[++cnt].v = v; e[cnt].nxt = head[u]; head[u] = cnt; } inline void get_siz(int u) { siz[u] = 1; for (int i = head[u];~i;i = e[i].nxt) { int v = e[i].v; get_siz(v); siz[u] += siz[v]; } } inline void dfs(int u) { if (c[u] > siz[u]-1) { cout << "NO" << endl; exit(0); } int xx = 0; for (int i = 1;i <= n;i++) { if (!vis[i]) xx++; if (xx == c[u]+1) { p[u] = i; vis[i] = 1; break; } } for (int i = head[u];~i;i = e[i].nxt) dfs(e[i].v); } int main() { scanf("%d",&n); int root; memset(head,-1, sizeof(head)); cnt = 0; for (int i = 1;i <= n;i++) { int f; scanf("%d%d",&f,&c[i]); if (f == 0) root = i; else add_edge(f,i); } get_siz(root); tot = 1; dfs(root); printf("YES "); for (int i = 1;i <= n;i++) printf("%d ",p[i]); printf(" "); return 0; }