1283F

贪心

一条边的价值肯定大于其子树里边的价值 那么先将叶子节点对应的边放进一个$set$ 从后往前扫 每次选$set$里最小的配对 如果出现新的叶子加入$set$ 每条边的价值就是自己以及子树中最大的编号 

有点类似超级钢琴的贪心 不过简单很多

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int n;
int d[maxn], a[maxn], dp[maxn];
int main() {
    scanf("%d", &n);
    for(int i = 1; i < n; ++i) {
        scanf("%d", &a[i]);
        ++d[a[i]];
    }
    set<pair<int, int> > s;
    for(int i = 1; i <= n; ++i) {
        dp[i] = i;
        if(!d[i]) {
            s.insert(make_pair(i, i));
        }
    }
    vector<pair<int, int> > ans;
    for(int i = n - 1; i; --i) {
        if(s.empty()) {
            puts("-1");
            return 0;
        }
        auto o = *s.begin();
        s.erase(s.begin());
        dp[a[i]] = max(dp[a[i]], o.first);
        ans.emplace_back(a[i], o.second);
        if(!--d[a[i]]) {
            s.insert(make_pair(dp[a[i]], a[i]));
        }
    }
    printf("%d
", a[1]);
    for(int i = n - 2; ~i; --i) {
        printf("%d %d
", ans[i].first, ans[i].second);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/19992147orz/p/12237192.html