题目大意:
要求构造一个n个节点的二叉树(每个节点拥有不超过2个孩子),节点1为根,要使所有节点到根的距离之和为d。要求先判断可不可以构造,如果可以输出“YES”,下一行输出2到n号节点的父亲节点,否则输出“NO”。有多组询问。
思路:
首先不难想到深度和最小的那种就是满二叉树的形式。然后我们再考虑移动一个节点到下一层去。 就是这么简单
#include <algorithm> #include <string> #include <string.h> #include <vector> #include <map> #include <stack> #include <set> #include <queue> #include <math.h> #include <cstdio> #include <iomanip> #include <time.h> #include <bitset> #include <cmath> #include <sstream> #include <iostream> #define LL long long #define INF 0x3f3f3f3f #define ls nod<<1 #define rs (nod<<1)+1 const double eps = 1e-10; const int maxn = 5e3 + 10;; const LL mod = 1e9 + 7; int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;} using namespace std; int fa[maxn],dep[maxn]; vector<int> vec[maxn]; int main() { int T; cin >> T; while (T--) { int n,m; cin >> n >> m; for (int i = 1;i <= n;i++) dep[i] = 0,fa[i] = 0,vec[i].clear(); vec[0].push_back(1); int maxx = 0; for (int i = 2;i <= n;i++) { dep[i] = dep[i>>1] + 1; vec[dep[i]].push_back(i); maxx = max(maxx,dep[i]); m -= dep[i]; } if (m < 0) { cout << "NO" << endl; continue; } bool flag = true; while (m) { int change = maxx; while (change >= 0 && vec[change].size() == 1) change--; if (change <= 0) { cout << "NO" << endl; flag = false; break; } int nod = vec[change][vec[change].size()-1]; vec[change].pop_back(); vec[change+1].push_back(nod); maxx = max(maxx,change+1); m--; } if (flag) { cout << "YES" << endl; for (int i = 1;i <= n;i++) { for (int j = 0;j < vec[i].size();j++) fa[vec[i][j]] = vec[i-1][j>>1]; } for (int i = 2;i <= n;i++) { cout << fa[i] << " "; } cout << endl; } } return 0; }