题目链接:https://codeforces.com/contest/1287/problem/D
题目大意:给出每个点的父亲和该点的子树中含有值比该点值小的点个数,求每个点的值
题目思路:讲道理,又是直接自闭。。构造题。首先显而易见,如果想要孩子中小于当前值的数字等于x个,那首先至少需要有x个孩子,如果没有这么多个孩子直接白给,其他情况都是没问题。
有两种常见的做法:
删除法
删除法的做法非常简单,就是直接dfs,每次给当前点赋的值就是还没有用到的数字中第c[u]个数字(从0开始数)
这种做法的正确性在于,首先当前数字是第c[u]个,那么,只要前面c[u]-1个数字如果都是该点的孩子的值,那么答案成立。由于孩子的数量大于等于c[u],给孩子赋值又是按照顺序来,所以前面几个数字一定会赋给它的孩子。
插入法
插入法的做法其实跟删除法异曲同工。不过插入法是自顶向下时直接赋值,先给父亲赋值,而插入法是先处理孩子。每次都把当前点插入到一个vector中,每次都插入到c[u]这个位置,由于一定是孩子插完才插当前点,所以vector中的元素一定大于等于c[u]。这个的正确性在于,每当你在插入一棵子树时,这棵子树的点就占据了前面的部分,那么在往里头插,每次孩子的数量又一定大于等于c[u],所以一定能插到自己子树的这部分内,也就是每次的插入一定都符合自己作为根的子树的合法位置,也就保证了答案的合法。
其实说的头头是道,想的也非常有道理,但还是感觉哪里有点怪怪的,就是感觉以后再遇到相同类型的题还是很难想到,可能还是刷题量没够吧。
以下是代码:
删除法
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
const int MAXN = 2e3+5;
int n,x,c[MAXN],vis[MAXN],ans[MAXN],siz[MAXN],flag;
vector<int>v[MAXN];
void dfs(int u){
if(flag)return;
int pos=0;
siz[u]=1;
rep(i,1,n){
if(vis[i]){
if(pos==c[u]){
vis[i]=0;
ans[u]=i;
break;
}
pos++;
}
}
int len=v[u].size();
rep(i,0,len-1){
int y=v[u][i];
dfs(y);
siz[u]+=siz[y];
}
if(c[u]>siz[u]-1){
flag=1;
return;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>n){
memset(vis,0,sizeof(vis));
memset(siz,0,sizeof(siz));
rep(i,1,n){
v[i].clear();
vis[i]=i;
}
int root;
rep(i,1,n){
cin>>x>>c[i];
if(!x)root=i;
else v[x].push_back(i);
}
flag=0;
dfs(root);
if(flag){
cout<<"NO"<<endl;
continue;
}
cout<<"YES"<<endl;
rep(i,1,n){
cout<<ans[i]<<" ";
}cout<<endl;
}
return 0;
}
插入法
By smilestruggler, contest: Codeforces Round #612 (Div. 2), problem: (D) Numbers on Tree, Accepted, #
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
const int MAXN = 2e3+5;
int n,x,c[MAXN],vis[MAXN],ans[MAXN],siz[MAXN],flag;
vector<int>v[MAXN],g;
void dfs(int u){
if(flag)return;
int len=v[u].size();
siz[u]=1;
rep(i,0,len-1){
int y=v[u][i];
dfs(y);
siz[u]+=siz[y];
}
if(c[u]>siz[u]-1){
flag=1;
return;
}
if(flag)return;
g.insert(g.begin()+c[u],u);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>n){
memset(vis,0,sizeof(vis));
memset(siz,0,sizeof(siz));
rep(i,1,n){
v[i].clear();
vis[i]=i;
}
g.clear();
int root;
rep(i,1,n){
cin>>x>>c[i];
if(!x)root=i;
else v[x].push_back(i);
}
flag=0;
dfs(root);
if(flag){
cout<<"NO"<<endl;
continue;
}
cout<<"YES"<<endl;
rep(i,0,n-1){
ans[g[i]]=i+1;
}
rep(i,1,n){
cout<<ans[i]<<" ";
}cout<<endl;
}
return 0;
}