【cf1286B】B. Numbers on Tree(贪心)
题意:
给出一颗有根树,每个结点有一个权值\(a_i,1\leq a_i\leq 10^9\);同时,每个结点有一个值\(c_i\),表示其子树中有多少个结点,满足\(a_j<a_i,j\in son_i\)。
现在只知道这棵树的\(c_i\),要求构造一种合法的权值序列,满足要求。
思路:
- \(n\)只有\(2000\),所以可以考虑\(O(n^2)\)的做法。
- 对于一颗子树,假设其大小为\(sz\),那么我们可以认为树的权值由\(1\)~\(sz\)组成且不重复。那么对于一个结点来说,若其为第\(k\)大,那么就赋与第\(k\)个没有出现的权值。
- 其余结点同理,递归处理即可。
最后记得检验一下是否合法,简单粗暴的方法再跑次\(dfs\)即可。
代码如下:
/*
* Author: heyuhhh
* Created Time: 2020/1/28 10:59:22
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2000 + 5;
int n;
bool chk[N];
vector <int> G[N];
int a[N], c[N];
void dfs(int u) {
int T = 0;
for(int i = 1; i < N; i++) {
if(!chk[i]) ++T;
if(T == c[u] + 1) {
a[u] = i;
chk[i] = true;
break;
}
}
for(auto v : G[u]) dfs(v);
}
int dfs2(int u, int x) {
int res = (a[u] < x);
for(auto v : G[u]) res += dfs2(v, x);
return res;
}
void run(){
int rt;
for(int i = 1; i <= n; i++) {
int p; cin >> p >> c[i];
if(p == 0) rt = i;
else G[p].push_back(i);
}
dfs(rt);
for(int i = 1; i <= n; i++) {
int x = dfs2(i, a[i]);
if(x != c[i]) {
cout << "NO" << '\n';
return;
}
}
cout << "YES" << '\n';
for(int i = 1; i <= n; i++) cout << a[i] << ' ';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
while(cin >> n) run();
return 0;
}
重要的是自信,一旦有了自信,人就会赢得一切。