D. Numbers on Tree---思维/数据结构/dfs

Evlampiy was gifted a rooted tree. The vertices of the tree are numbered from 1 to n. Each of its vertices also has an integer ai written on it. For each vertex i, Evlampiy calculated ci — the number of vertices j in the subtree of vertex i, such that aj<ai.
在这里插入图片描述
Illustration for the second example, the first integer is ai and the integer in parentheses is ci
After the new year, Evlampiy could not remember what his gift was! He remembers the tree and the values of ci, but he completely forgot which integers ai were written on the vertices.

Help him to restore initial integers!

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

The next n lines contain descriptions of vertices: the i-th line contains two integers pi and ci (0≤pi≤n; 0≤ci≤n−1), where pi is the parent of vertex i or 0 if vertex i is root, and ci is the number of vertices j in the subtree of vertex i, such that aj<ai.

It is guaranteed that the values of pi describe a rooted tree with n vertices.

Output
If a solution exists, in the first line print “YES”, and in the second line output n integers ai (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 ai are between 1 and 109.

If there are no solutions, print “NO”.

Examples
inputCopy
3
2 0
0 2
2 0
outputCopy
YES
1 2 1
inputCopy
5
0 1
1 3
2 1
3 0
2 0
outputCopy
YES
2 3 2 1 2

解析:
首先我们要证明n个节点一定可以放1-n的数字:

因为1-n的数字都是不同的,那么不会有相对大小的问题,不会有节点之间相互影响而导致答案错误。放相同值的节点也就是少一个差值,我们完全可以用放的方式去避免,比如小的放在大的上面。
然后证明节点Ci的值一定小于等于其节点个数,则一定存在方案:
我们从顶点开始放,没放的数字我们是一定知道的(因为只有1-n)。所以放的时候相当于在没放的数字中找到第ci+1大的数字,放上去。即可满足条件,继续向下递归。

思路来自于:https://blog.csdn.net/weixin_43826249/article/details/103855447


#include<bits/stdc++.h>
using namespace std;
const int N=2010;
int idx,n,root,p,h[N];
int sz[N],vis[N],c[N],num[N];
struct node
{
	int to,next;
}e[N];
void add(int u,int v)
{
	
	e[idx].to=v;
	e[idx].next=h[u];
	h[u]=idx++;
}
void dfs_in(int x) //判断有无解;如果第i个节点的ci加上1大于节点个数肯定无解的。 
{
	sz[x]=1;
	for(int i=h[x];i!=-1;i=e[i].next)
	{
		int v=e[i].to;
		dfs_in(v);
		sz[x]+=sz[v];
	}
}
void dfs(int x)
{
	int cnt=0;
	for(int i=1;i<=n;i++)
	{
		if(!vis[i]) ++cnt; //这边就是计算在没放的数字中第cnt个。
		if(c[x]+1==cnt)//在未放的数字中找第ci+1个数字
		{
			num[x]=i;
			vis[i]=1;
			break;
		}
	}
	for(int j=h[x];j!=-1;j=e[j].next) dfs(e[j].to);
}
int main()
{
	memset(h,-1,sizeof h);
	scanf("%d",&n);
	for(int i=1;i<=n;i++) 
	{
		scanf("%d %d",&p,&c[i]);
		if(p==0) root=i;
		else add(p,i);
	}
	dfs_in(root);
	for(int i=1;i<=n;i++)
	{
		if(c[i]+1>sz[i])
		{
			puts("NO");
			return 0;
		}
	}
	dfs(root);
	puts("YES");
	for(int i=1;i<=n;i++) printf("%d ",num[i]);
	cout<<endl;
	return 0;
}

发布了284 篇原创文章 · 获赞 6 · 访问量 3792

猜你喜欢

转载自blog.csdn.net/qq_43690454/article/details/103997046