题目链接
大意:给你一个序列,让你构造一颗合法的有根树,满足:
序列的第 i t h i_{th} ith数代表的是第 i t h i_{th} 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;
}