题目链接
大意:给你一个序列,让你构造一颗合法的有根树,满足:
序列的第 ith数代表的是第 ith大的边的父亲节点,边的价值定义为:子树内所有节点编号的2的幂次方和。
思路:直接逆向拓扑排序,开一个优先队列,把入度为0的先进队,倒着扫,把最小的和当前点连边即可。
细节见代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
int main() {
ios::sync_with_stdio(false);
int n;
cin >> n;
vector<int> a(n + 1);
vector<int> d(n + 1, 0);
for (int i = 1; i < n; i++) {
cin >> a[i];
d[a[i]]++;
}
priority_queue<int> q;
for (int i = 1; i <= n; i++) {
if (!d[i])
q.push(-i);
}
cout << a[1] << '\n';
for (int i = n - 1; i >= 1; i--) {
cout << -q.top() << ' ' << a[i] << '\n';
q.pop();
if (--d[a[i]] == 0)
q.push(-a[i]);
}
return 0;
}