2000分的構造,看了題解才發現如何構造,發現是個構造好題
題意:
給出一棵樹,樹上每個節點有權值a,屬性c,代表c的子樹上小於其權值的點的個數
現在給出 樹的結構及各節點c的值
問是否能成功分配a的值使得題意滿足條件
題目思路:
首先不得不說...賊秀
首先判斷 是否可以構造出來,也就是說 c是否大於等於子樹節點數
如果可以構造出來,那麼存在一個結論:將樹的各節點 分配一下 1~n的全排列,那麼一定存在一種可行方案。
既然知道可行那麼就直接構造就好了
爲了確保 下面不會再次影響到上面
我們從頂點更新,假設當前節點c爲2,我們就從1~n中還沒有選的第c+1大賦值,那麼接下來他的子樹中一定有小於c+1的值,也就是存在c個小於他的節點
構造完成:
Code:
/*** keep hungry and calm CoolGuang!***/
//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18;
const int maxn=2e5+6;
const int mod=1e9+7;
const double eps=1e-9;
inline bool read(ll &num)
{char in;bool IsN=false;
in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m;
int root;
int sz[maxn];
int tot=0;
vector<int>v[maxn];
int p[maxn];
int vis[maxn];
int res[maxn];
int cnt=0;
int f=0;
void dfs(int u){
sz[u]=1;
int cot=0;
for(int i=1;i<=n;i++){
if(!vis[i]){
cot++;
if(cot==p[u]+1){
vis[i]=1;
res[u]=i;
break;
}
}
}
for(int e:v[u]){
dfs(e);
sz[u]+=sz[e];
}
if(p[u]>=sz[u]) f=1;
}
int main(){
read(n);
for(int i=1;i<=n;i++){
int x;scanf("%d%d",&x,&p[i]);
if(x) v[x].push_back(i);
else root=i;
}
dfs(root);
if(!f){
printf("YES\n");
for(int i=1;i<=n;i++)
printf("%d ",res[i]);
}
else printf("NO\n");
return 0;
}
/**
4 7 8 6
6
1 2 3 3 3 3
2 4 2 4 5 5
2+6+11+6+2
**/