「Daily OI Round 1」Tree 题解
下面是出题人题解:
因为是到根节点的距离,所以设根节点深度为
subtask0
暴力可做,枚举每个点的父亲节点,时间复杂度
subtask1
节点数量为
subtask2
很显然,构造菊花图,然后判断深度之和是否等于
subtask3
还是构造菊花图,但是当
subtask4
给随机数算法的分。
subtask5
很显然,对于深度相同的节点,把它们的儿子都移到这个深度的某个节点下面是可行的,那么这时题目变成了每一层至少
题目还要求最大深度最小,枚举最大深度,然后每个深度(除了根节点所在深度)都先安排
如果剩下
那么有解当且仅当
确定每个点的深度,然后深度
深度最大为
#include<bits/stdc++.h>
#define ll long long
#define N 100005
using namespace std;
ll t,k,n,d,i,j,l,p,o,temp,dep[N],tot,ans[N];
int main(){
ios::sync_with_stdio(false);
cin>>t;
while(t--){
tot=0;
cin>>n>>d>>k;
if(n==1){
if(d==0){
cout<<"YES\n";
continue;
}
else{
cout<<"NO\n";
continue;
}
}
temp=0;
for(i=1;i<=n;i++){
if(i*(i+1)/2*k>d||i*k+1>n) break;
j = d-i*(i+1)/2*k;
l = (n-i*k-1);
if(l*i>=j&&l<=j){
j=i*l-j;
temp=1;
cout<<"YES\n";
for(p=1;p<=i;p++){
for(o=1;o<=k;o++) dep[++tot]=p;
}
for(p=1;p<=l;p++) dep[++tot]=i;
for(p=tot-l+1;p<=tot;p++){
if(dep[p]-1>=j){
dep[p]-=j;
break;
}
else j-=(dep[p]-1),dep[p]=1;
}
sort(dep+1,dep+tot+1);
ans[0] = 1;
for(p=1;p<=tot;p++) cout<<ans[dep[p]-1]<<" ",ans[dep[p]]=p+1;
cout<<endl;
break;
}
}
if(!temp) cout<<"NO\n";
}
return 0;
}